|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1989-1999 Microsoft Corporation
Module Name:
semutil.cxx
Abstract:
semantic analysis utility routines
Notes:
Author:
GregJen 28-Oct-1993 Created.
Notes:
----------------------------------------------------------------------------*/
#pragma warning ( disable : 4514 4710 )
/****************************************************************************
* include files ***************************************************************************/
#include "nulldefs.h"
extern "C" { #include <stdio.h>
#include <stdlib.h>
#include <string.h>
} #include "allnodes.hxx"
#include "semantic.hxx"
#include "symtable.hxx"
#include "cmdana.hxx"
/****************************************************************************
* local data ***************************************************************************/
/****************************************************************************
* externs ***************************************************************************/
extern SymTable * pBaseSymTbl; extern ATTR_SUMMARY DisallowedAttrs[INTERNAL_NODE_END]; extern BOOL IsTempName( char * ); extern CMD_ARG * pCommand;
/****************************************************************************
* definitions ***************************************************************************/
void WALK_CTXT::FindImportantPosition(tracked_node & Posn) { WALK_CTXT * pCurCtxt = this; WALK_CTXT * pParCtxt; node_skl * pNode;
// walk up until we find one whose PARENT was not important
while ( (pParCtxt=(WALK_CTXT *)pCurCtxt->GetParentContext()) != 0 && ( pParCtxt->IsImportantPosition() ) ) { pCurCtxt = pParCtxt; }
// continue walking up until we find one with a position
do { pNode = pCurCtxt->GetParent(); pNode->GetPositionInfo( Posn ); pCurCtxt = (WALK_CTXT *) pCurCtxt->GetParentContext(); } while( !Posn.HasTracking() && pCurCtxt ); }
void SEM_ANALYSIS_CTXT::CheckAttributes() { ATTR_VECTOR & BadAttrs = DisallowedAttrs[ GetParent()->NodeKind() ]; ATTR_VECTOR ExcessAttrs; ATTR_T Attr; node_base_attr * pAttr; char * pAttrName;
MASKED_COPY_ATTR( ExcessAttrs, *(pDownAttrList->GetSummary()), BadAttrs ); while (!IS_CLEAR_ATTR( ExcessAttrs ) ) { Attr = CLEAR_FIRST_SET_ATTR( ExcessAttrs ); pAttr = ExtractAttribute( Attr ); pAttrName = pAttr->GetNodeNameString();
if (pAttr->IsAcfAttr() ) AcfError( (acf_attr *)pAttr, GetParent(), *this, INAPPLICABLE_ATTRIBUTE, pAttrName); else SemError( GetParent(), *this, INAPPLICABLE_ATTRIBUTE ,pAttrName);
} }
void SEM_ANALYSIS_CTXT::RejectAttributes() { ATTR_VECTOR ExcessAttrs; ATTR_T Attr; node_base_attr * pAttr; char * pAttrName;
COPY_ATTR( ExcessAttrs, *(pDownAttrList->GetSummary())); while (!IS_CLEAR_ATTR( ExcessAttrs ) ) { Attr = CLEAR_FIRST_SET_ATTR( ExcessAttrs ); pAttr = ExtractAttribute( Attr ); pAttrName = pAttr->GetNodeNameString();
if (pAttr->IsAcfAttr() ) AcfError( (acf_attr *)pAttr, GetParent(), *this, INAPPLICABLE_ATTRIBUTE, pAttrName); else SemError( GetParent(), *this, INAPPLICABLE_ATTRIBUTE ,pAttrName);
} }
//
// resolve forward declarations
//
named_node * node_forward::ResolveFDecl() { if ( !GetChild() ) { named_node * pRef = pSymTbl->SymSearch( SKey );
if (pRef && ( pRef != this ) && ( pRef->NodeKind() != NODE_FORWARD ) ) { SetChild( pRef ); } } return (named_node *) GetChild(); }
void node_proc::AddExplicitHandle ( SEM_ANALYSIS_CTXT* pParentCtxt, unsigned int uParamNumber ) { node_skl * pHand; node_param * pParm;
// only add the handle once
if ( !strcmp( GetChild()->GetSymName(), "IDL_handle" ) ) return;
GetBaseTypeNode( &pHand, SIGN_UNDEF, SIZE_UNDEF, TYPE_HANDLE_T, 0 );
// set up [in] param "IDL_handle", pointing to handle_t, add as first parameter
pParm = new node_param; pParm->SetSymName( "IDL_handle" ); pParm->SetChild( pHand ); pParm->SetAttribute( new battr( ATTR_IN ) );
if ( uParamNumber == 1 ) { AddFirstMember( pParm ); } else { AddSecondMember( pParm ); }
// update the information for the parameter
pParm->SemanticAnalysis( pParentCtxt );
fHasExplicitHandle = TRUE; fHasAtLeastOneIn = TRUE; }
void node_proc::AddFullAsyncHandle ( SEM_ANALYSIS_CTXT* pParentCtxt, node_skl* pType, char* szTypeName ) { const char* szNameSuffix = "_AsyncHandle"; char* szFullName = new char[strlen(GetSymName()) + strlen(szNameSuffix) + 1];
strcpy(szFullName, GetSymName()); strcat(szFullName, szNameSuffix); node_skl* pAsyncHandle = new node_async_handle( szTypeName );
if ( pType ) { pAsyncHandle->SetChild( pType ); } node_param* pParm = new node_param;
pParm->SetSymName( szFullName ); pParm->SetChild( pAsyncHandle );
pParm->SetAttribute( new battr( ATTR_IN ) ); AddFirstMember( pParm ); pParm->SemanticAnalysis( pParentCtxt ); SetHasAsyncHandle(); pParm->SetIsAsyncHandleParam(); fHasAtLeastOneIn = TRUE; }
BOOL node_base_type::RangeCheck( __int64 Val ) { NODE_T Kind = NodeKind();
switch ( Kind ) { case NODE_BOOLEAN: return ( Val >= 0 ) && ( Val <= 1 ); case NODE_SHORT: if ( FInSummary( ATTR_UNSIGNED ) ) return ( Val >= 0 ) && ( Val <= _UI16_MAX ); else return ( Val >= _I16_MIN ) && ( Val <= _I16_MAX ); case NODE_BYTE: return ( Val >= 0 ) && ( Val <= 255 ); case NODE_CHAR: if ( FInSummary( ATTR_UNSIGNED ) ) return ( Val >= 0 ) && ( Val <= 255 ); else if ( FInSummary( ATTR_SIGNED ) ) return ( Val >= -128 ) && ( Val <= 127 ); else if ( pCommand->GetCharOption() == CHAR_SIGNED ) return ( Val >= 0 ) && ( Val <= 255 ); else return ( Val >= -128 ) && ( Val <= 127 ); case NODE_SMALL: if ( FInSummary( ATTR_UNSIGNED ) ) return ( Val >= 0 ) && ( Val <= 255 ); else if ( FInSummary( ATTR_SIGNED ) ) return ( Val >= -128 ) && ( Val <= 127 ); else if ( pCommand->GetCharOption() == CHAR_UNSIGNED ) return ( Val >= -128 ) && ( Val <= 127 ); else return ( Val >= 0 ) && ( Val <= 255 ); case NODE_LONG: case NODE_INT32: case NODE_INT: if ( FInSummary( ATTR_UNSIGNED ) ) return ( Val >= 0 ) && ( Val <= _UI32_MAX ); else return ( Val >= _I32_MIN ) && ( Val <= _I32_MAX ); case NODE_INT3264: if ( ! pCommand->Is64BitEnv() ) { if ( FInSummary( ATTR_UNSIGNED ) ) return ( Val >= 0 ) && ( Val <= _UI32_MAX ); else return ( Val >= _I32_MIN ) && ( Val <= _I32_MAX ); } // else fall through to 64b integral
case NODE_HYPER: case NODE_INT64: case NODE_INT128: return TRUE; } return TRUE; }
BOOL node_base_type::IsAssignmentCompatible( node_base_type * pOther ) { unsigned long MySize = GetSize(); unsigned long HisSize = pOther->GetSize();
// tbd - fill in more cases
if ( MySize < HisSize ) return FALSE;
// unsigned <= signed
if ( FInSummary( ATTR_UNSIGNED ) && !pOther->FInSummary( ATTR_UNSIGNED ) ) return FALSE;
// signed <= unsigned ( only OK if dest is larger )
if ( pOther->FInSummary( ATTR_UNSIGNED ) && FInSummary( ATTR_SIGNED ) && (MySize <= HisSize) ) return FALSE;
if ( ( NodeKind() == NODE_BOOLEAN ) && ( pOther->NodeKind() != NODE_BOOLEAN ) ) return FALSE;
return TRUE; }
char * GetErrorNamePrefix( node_skl * pNode ) { if ( !pNode ) return NULL;
switch ( pNode->NodeKind() ) { case NODE_FIELD: return " Field "; case NODE_STRUCT: return " Struct "; case NODE_UNION: return " Union "; case NODE_ENUM: return " Enum "; case NODE_PARAM: return " Parameter "; case NODE_PROC: return " Procedure "; case NODE_INTERFACE: case NODE_INTERFACE_REFERENCE: return " Interface "; case NODE_PIPE_INTERFACE: return " Object Pipe "; case NODE_DEF: return " Type "; case NODE_LIBRARY: return " Library "; case NODE_MODULE: return " Module "; case NODE_COCLASS: return " Coclass "; case NODE_DISPINTERFACE: return " Dispinterface "; default: return NULL; } }
#define SUFFIX_SIZE 1000
#define CONTEXT_STR_SIZE 1000
void GetSemContextString( char * pResult, node_skl * pNode, WALK_CTXT * pCtxt ) { node_skl * pBase = NULL; node_skl * pParent = NULL; node_skl * pUsage = NULL; char * pPrefix;
pResult[0] = '\0';
if ( !pNode ) { pNode = ( pCtxt ) ? pCtxt->GetParent() : NULL; }
// compute base part and parent part
while ( pCtxt && !pParent && pNode ) { switch ( pNode->NodeKind() ) { case NODE_FIELD: case NODE_PARAM: pBase = pNode; break; case NODE_STRUCT: case NODE_UNION: case NODE_ENUM: case NODE_PROC: case NODE_INTERFACE: case NODE_PIPE_INTERFACE: case NODE_INTERFACE_REFERENCE: case NODE_DEF: case NODE_LIBRARY: case NODE_MODULE: case NODE_COCLASS: case NODE_DISPINTERFACE: pParent = pNode; break; }
pCtxt = pCtxt->GetParentContext(); pNode = ( pCtxt ) ? pCtxt->GetParent() : NULL; }
// compute usage part (param or proc or interface)
// note that pCtxt is one level up above the current pNode
pCtxt = pCtxt->GetParentContext(); while ( pCtxt && ! pUsage ) { switch ( pCtxt->GetParent()->NodeKind() ) { // stop at the top-most level ( child of interface, or proc )
// therefore highest type/proc/param
case NODE_INTERFACE: case NODE_PIPE_INTERFACE: case NODE_PROC: case NODE_LIBRARY: case NODE_MODULE: case NODE_COCLASS: case NODE_DISPINTERFACE: pUsage = pNode; break; }
pNode = ( pCtxt ) ? pCtxt->GetParent() : NULL; pCtxt = pCtxt->GetParentContext(); }
if ( pBase || pParent || pUsage ) { strcat( pResult, "[");
if ( pBase ) { pPrefix = GetErrorNamePrefix( pBase ); if ( pPrefix ) strcat( pResult, pPrefix ); if ( !IsTempName( pBase->GetSymName() ) ) { strcat( pResult, "'"); strcat( pResult, pBase->GetSymName() ); strcat( pResult, "' "); } }
if ( pParent ) { if ( !IsTempName( pParent->GetSymName() ) ) { if ( pBase ) strcat(pResult, "of"); pPrefix = GetErrorNamePrefix( pParent ); if ( pPrefix ) strcat( pResult, pPrefix ); strcat( pResult, "'"); strcat( pResult, pParent->GetSymName() ); strcat( pResult, "' "); } else { pPrefix = GetErrorNamePrefix( pBase ); if ( pPrefix && !pBase ) strcat( pResult, pPrefix ); } }
if ( pUsage ) { strcat( pResult, "("); pPrefix = GetErrorNamePrefix( pUsage ); if ( pPrefix ) strcat( pResult, pPrefix ); strcat( pResult, "'"); strcat( pResult, pUsage->GetSymName() ); strcat( pResult, "' )"); }
strcat( pResult, " ]"); } }
void SemError( node_skl * pNode, WALK_CTXT & Ctxt, STATUS_T ErrNum, char * pExtra ) { ErrorInfo ErrStats( ErrNum );
// if the error is not relevant to this compile, return right away
if ( !ErrStats.IsRelevant() ) return;
short CurLen = 1; // for the null byte
char Suffix[SUFFIX_SIZE]; char ContextStr[ CONTEXT_STR_SIZE ]; char * pSuffix = Suffix; char * pFile; short Line; tracked_node Posn((void*)NULL); WALK_CTXT * pCurCtxt; // extract file and line info, and context info
pCurCtxt = &Ctxt;
GetSemContextString( ContextStr, pNode, &Ctxt ); CurLen = short( CurLen + strlen( ContextStr ) );
// unless the string is REALLY long, just use stack space
if ( CurLen + 1 > SUFFIX_SIZE ) pSuffix = new char [CurLen + 1];
if ( pExtra || strlen( ContextStr ) ) { strcpy( pSuffix, ": " ); if ( pExtra ) strcat( pSuffix, pExtra );
// make sure pSuffix has a trailing space at this point
if ( pSuffix[ strlen(pSuffix) - 1 ] != ' ' ) { strcat( pSuffix, " " ); }
if ( strlen(ContextStr) ) { strcat( pSuffix, ContextStr ); } } else strcpy( pSuffix, "" );
// fetch the file position from the context stack
Ctxt.FindImportantPosition(Posn); Posn.GetLineInfo( pFile, Line);
ErrStats.ReportError( pFile, Line, pSuffix );
// clean up if we had to allocate space
if ( pSuffix != Suffix ) delete pSuffix; }
void AcfError( acf_attr * pAttr, node_skl * , WALK_CTXT & , STATUS_T ErrNum, char * pExtra ) { short CurLen = 1; // for the null byte
char Suffix[SUFFIX_SIZE]; char * pSuffix = Suffix; char * pName; char * pFile; short Line; tracked_node Posn((void*)NULL);
// extract file and line info, and context info
pName = pAttr->GetNodeNameString(); // <name>[: <extra>]
CurLen = short( CurLen + strlen(pName) ); CurLen = short( CurLen + ( (pExtra) ? strlen(pExtra) + 2 : 0 ) );
// unless the string is REALLY long, just use stack space
if ( CurLen + 1 > SUFFIX_SIZE ) pSuffix = new char [CurLen + 1];
strcpy( pSuffix, pName ); if (pExtra) { strcat( pSuffix, ": " ); strcat( pSuffix, pExtra ); }
// fetch the file position from the context stack
pAttr->Position.GetLineInfo( pFile, Line);
RpcError( pFile, Line, ErrNum, pSuffix );
// clean up if we had to allocate space
if ( pSuffix != Suffix ) delete pSuffix; }
BOOL CIDLIST::AddId(__int64 lId, char * szName) { IDLISTMEM ** pThis = &pHead; while (*pThis && (*pThis)->lId < lId) { pThis = &((*pThis)->pNext); } if (*pThis && (*pThis)->lId == lId) { if (_stricmp(szName, (*pThis)->szName)) return FALSE; else return TRUE; } IDLISTMEM * pNew = new IDLISTMEM; pNew->lId = lId; pNew->pNext = *pThis; pNew->szName = szName; *pThis = pNew; return TRUE; }
/*
Nishad
bool node_base_type::IsCompatibleType( TypeSet set ) { bool fReturnCode = false; NODE_T nodeKind = NodeKind();
switch ( set ) { case ts_UnsignedFixedPoint: fReturnCode = ( nodeKind == NODE_INT128 || nodeKind == NODE_HYPER || nodeKind == NODE_INT64 || nodeKind == NODE_INT32 || nodeKind == NODE_LONG || nodeKind == NODE_LONGLONG || nodeKind == NODE_SHORT || nodeKind == NODE_INT || nodeKind == NODE_SMALL || nodeKind == NODE_CHAR || nodeKind == NODE_BOOLEAN || nodeKind == NODE_BYTE ) && IsUnsigned(); break; case ts_FixedPoint: fReturnCode = ( nodeKind == NODE_INT128 || nodeKind == NODE_HYPER || nodeKind == NODE_INT64 || nodeKind == NODE_INT32 || nodeKind == NODE_LONG || nodeKind == NODE_LONGLONG || nodeKind == NODE_SHORT || nodeKind == NODE_INT || nodeKind == NODE_SMALL || nodeKind == NODE_CHAR || nodeKind == NODE_BOOLEAN || nodeKind == NODE_BYTE ); break; case ts_FloatingPoint: fReturnCode = ( nodeKind == NODE_FLOAT || nodeKind == NODE_DOUBLE || nodeKind == NODE_FLOAT80 || nodeKind == NODE_FLOAT128 ); break; case ts_Character: fReturnCode = ( nodeKind == NODE_CHAR || nodeKind == NODE_BYTE || nodeKind == NODE_WCHAR_T ); break; case ts_String: // TBD
break; case ts_Interface: // TBD
break; }
return fReturnCode; }
*/
|