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.
1443 lines
33 KiB
1443 lines
33 KiB
/*****************************************************************************/
|
|
/** Microsoft LAN Manager **/
|
|
/** Copyright(c) Microsoft Corp., 1987-1990 **/
|
|
/*****************************************************************************/
|
|
/*****************************************************************************
|
|
File : gramutil.cxx
|
|
Title : grammar utility routines
|
|
Description : contains associated routines for the grammar (pass 1)
|
|
History :
|
|
05-Aug-1991 VibhasC Created
|
|
*****************************************************************************/
|
|
/****************************************************************************
|
|
* include files
|
|
***************************************************************************/
|
|
|
|
#include "nulldefs.h"
|
|
extern "C" {
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
}
|
|
#include "lextable.hxx"
|
|
#include "nodeskl.hxx"
|
|
#include "basetype.hxx"
|
|
#include "miscnode.hxx"
|
|
#include "procnode.hxx"
|
|
#include "attrnode.hxx"
|
|
#include "compnode.hxx"
|
|
#include "typedef.hxx"
|
|
#include "gramutil.hxx"
|
|
#include "filehndl.hxx"
|
|
#include "idict.hxx"
|
|
#include "control.hxx"
|
|
#include "cmdana.hxx"
|
|
#include "baduse.hxx"
|
|
|
|
/****************************************************************************
|
|
* external data
|
|
***************************************************************************/
|
|
|
|
extern CMD_ARG * pCommand;
|
|
extern class _nfa_info * pImportCntrl;
|
|
extern pre_type_db * pPreAllocTypes;
|
|
extern SymTable * pBaseSymTbl;
|
|
extern node_error * pErrorTypeNode;
|
|
extern short CompileMode;
|
|
extern idict * pPreAllocatedBitAttrDict;
|
|
extern node_e_attr * pErrorAttrNode;
|
|
extern CCONTROL * pCompiler;
|
|
extern LexTable * pMidlLexTable;
|
|
extern IINFODICT * pInterfaceInfoDict;
|
|
extern short ImportLevel;
|
|
extern BOOL fObject;
|
|
|
|
/****************************************************************************
|
|
* external functions
|
|
***************************************************************************/
|
|
|
|
extern char * GetSizeName( short );
|
|
extern char * GetSignName( short );
|
|
extern char * GetTypeName( short );
|
|
extern STATUS_T GetBaseTypeNode( node_skl **, short, short, short);
|
|
extern type_node_list* GenerateFieldAttribute(NODE_T, expr_list *);
|
|
|
|
extern void ApplySummaryAttributes( node_skl *, ATTR_SUMMARY * );
|
|
extern char * GetExpectedSyntax( char *, short );
|
|
extern int GetExpectedChar( short );
|
|
extern BOOL IsValidSizeOfType( node_skl * );
|
|
extern void CheckGlobalNamesClash( SymKey );
|
|
extern void CheckSpecialForwardTypedef( node_skl *,
|
|
node_skl *,
|
|
type_node_list *);
|
|
/****************************************************************************
|
|
* local functions
|
|
***************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* local definitions
|
|
***************************************************************************/
|
|
struct pre_init
|
|
{
|
|
unsigned short TypeSpec;
|
|
NODE_T NodeType;
|
|
ATTR_T Attr;
|
|
char * pSymName;
|
|
node_state NodeState;
|
|
};
|
|
struct pre_init PreInitArray[ PRE_TYPE_DB_SIZE ] =
|
|
{
|
|
{ /** float **/
|
|
MAKE_TYPE_SPEC( SIGN_UNDEF, SIZE_UNDEF, TYPE_FLOAT )
|
|
,NODE_FLOAT
|
|
,(ATTR_T)ATTR_NONE
|
|
,"float"
|
|
,NODE_STATE_ALL_SEMANTICS_DONE
|
|
}
|
|
,{ /** double **/
|
|
MAKE_TYPE_SPEC( SIGN_UNDEF, SIZE_UNDEF, TYPE_DOUBLE )
|
|
,NODE_DOUBLE
|
|
,(ATTR_T)ATTR_NONE
|
|
,"double"
|
|
,NODE_STATE_ALL_SEMANTICS_DONE
|
|
}
|
|
,{ /** signed hyper **/
|
|
MAKE_TYPE_SPEC( SIGN_SIGNED, SIZE_HYPER, TYPE_INT )
|
|
,NODE_HYPER
|
|
,(ATTR_T)ATTR_NONE
|
|
,"hyper"
|
|
,NODE_STATE_ALL_SEMANTICS_DONE
|
|
}
|
|
,{ /** unsigned hyper **/
|
|
MAKE_TYPE_SPEC( SIGN_UNSIGNED, SIZE_HYPER, TYPE_INT )
|
|
,NODE_HYPER
|
|
,(ATTR_T)ATTR_UNSIGNED
|
|
,"hyper"
|
|
,NODE_STATE_ALL_SEMANTICS_DONE
|
|
}
|
|
,{ /** signed long **/
|
|
MAKE_TYPE_SPEC( SIGN_SIGNED, SIZE_LONG, TYPE_INT )
|
|
,NODE_LONG
|
|
,(ATTR_T)ATTR_NONE
|
|
,"long"
|
|
,NODE_STATE_ALL_SEMANTICS_DONE
|
|
}
|
|
,{ /** unsigned long **/
|
|
MAKE_TYPE_SPEC( SIGN_UNSIGNED, SIZE_LONG, TYPE_INT )
|
|
,NODE_LONG
|
|
,(ATTR_T)ATTR_UNSIGNED
|
|
,"long"
|
|
,NODE_STATE_ALL_SEMANTICS_DONE
|
|
}
|
|
,{ /** signed int **/
|
|
MAKE_TYPE_SPEC( SIGN_SIGNED, SIZE_UNDEF, TYPE_INT )
|
|
,NODE_INT
|
|
,(ATTR_T)ATTR_NONE
|
|
,"int"
|
|
,(NODE_STATE_ALL_SEMANTICS_DONE | NODE_STATE_IS_NON_RPCABLE_TYPE)
|
|
}
|
|
,{ /** unsigned int **/
|
|
MAKE_TYPE_SPEC( SIGN_UNSIGNED, SIZE_UNDEF, TYPE_INT )
|
|
,NODE_INT
|
|
,(ATTR_T)ATTR_UNSIGNED
|
|
,"int"
|
|
,(NODE_STATE_ALL_SEMANTICS_DONE | NODE_STATE_IS_NON_RPCABLE_TYPE)
|
|
}
|
|
,{ /** signed short **/
|
|
MAKE_TYPE_SPEC( SIGN_SIGNED, SIZE_SHORT, TYPE_INT )
|
|
,NODE_SHORT
|
|
,(ATTR_T)ATTR_NONE
|
|
,"short"
|
|
,NODE_STATE_ALL_SEMANTICS_DONE
|
|
}
|
|
,{ /** unsigned short **/
|
|
MAKE_TYPE_SPEC( SIGN_UNSIGNED, SIZE_SHORT, TYPE_INT )
|
|
,NODE_SHORT
|
|
,(ATTR_T)ATTR_UNSIGNED
|
|
,"short"
|
|
,NODE_STATE_ALL_SEMANTICS_DONE
|
|
}
|
|
,{ /** signed small **/
|
|
MAKE_TYPE_SPEC( SIGN_SIGNED, SIZE_SMALL, TYPE_INT )
|
|
,NODE_SMALL
|
|
,(ATTR_T)ATTR_SIGNED
|
|
,"small"
|
|
,NODE_STATE_ALL_SEMANTICS_DONE
|
|
}
|
|
,{ /** small **//** NOTE : SMALL W/O SIGN IS A SPECIAL HACK FOR THE BACKEND **/
|
|
MAKE_TYPE_SPEC( SIGN_UNDEF, SIZE_SMALL, TYPE_INT )
|
|
,NODE_SMALL
|
|
,(ATTR_T)ATTR_NONE
|
|
,"small"
|
|
,NODE_STATE_ALL_SEMANTICS_DONE
|
|
}
|
|
,{ /** unsigned small **/
|
|
MAKE_TYPE_SPEC( SIGN_UNSIGNED, SIZE_SMALL, TYPE_INT )
|
|
,NODE_SMALL
|
|
,(ATTR_T)ATTR_UNSIGNED
|
|
,"small"
|
|
,NODE_STATE_ALL_SEMANTICS_DONE
|
|
}
|
|
,{ /** signed char **/
|
|
MAKE_TYPE_SPEC( SIGN_SIGNED, SIZE_CHAR, TYPE_INT )
|
|
,NODE_CHAR
|
|
,(ATTR_T)ATTR_SIGNED
|
|
,"char"
|
|
,NODE_STATE_ALL_SEMANTICS_DONE
|
|
}
|
|
,{ /** plain char **/
|
|
MAKE_TYPE_SPEC( SIGN_UNDEF, SIZE_CHAR, TYPE_INT )
|
|
,NODE_CHAR
|
|
,(ATTR_T)ATTR_NONE
|
|
,"char"
|
|
,NODE_STATE_ALL_SEMANTICS_DONE
|
|
}
|
|
,{ /** unsigned char **/
|
|
MAKE_TYPE_SPEC( SIGN_UNSIGNED, SIZE_CHAR, TYPE_INT )
|
|
,NODE_CHAR
|
|
,(ATTR_T)ATTR_UNSIGNED
|
|
,"char"
|
|
,NODE_STATE_ALL_SEMANTICS_DONE
|
|
}
|
|
,{ /** boolean **/
|
|
MAKE_TYPE_SPEC( SIGN_UNDEF, SIZE_UNDEF, TYPE_BOOLEAN )
|
|
,NODE_BOOLEAN
|
|
,(ATTR_T)ATTR_NONE
|
|
,"boolean"
|
|
,NODE_STATE_ALL_SEMANTICS_DONE
|
|
}
|
|
,{ /** byte **/
|
|
MAKE_TYPE_SPEC( SIGN_UNDEF, SIZE_UNDEF, TYPE_BYTE )
|
|
,NODE_BYTE
|
|
,(ATTR_T)ATTR_NONE
|
|
,"byte"
|
|
,NODE_STATE_ALL_SEMANTICS_DONE
|
|
}
|
|
,{ /** void **/
|
|
MAKE_TYPE_SPEC( SIGN_UNDEF, SIZE_UNDEF, TYPE_VOID )
|
|
,NODE_VOID
|
|
,(ATTR_T)ATTR_NONE
|
|
,"void"
|
|
,(NODE_STATE_ALL_SEMANTICS_DONE |
|
|
NODE_STATE_IMPROPER_IN_CONSTRUCT |
|
|
NODE_STATE_IS_NON_RPCABLE_TYPE)
|
|
}
|
|
,{ /** handle_t **/
|
|
MAKE_TYPE_SPEC( SIGN_UNDEF, SIZE_UNDEF, TYPE_HANDLE_T )
|
|
,NODE_HANDLE_T
|
|
,(ATTR_T)ATTR_NONE
|
|
,"handle_t"
|
|
,(NODE_STATE_ALL_SEMANTICS_DONE |
|
|
NODE_STATE_IMPROPER_IN_CONSTRUCT |
|
|
NODE_STATE_HANDLE )
|
|
}
|
|
,{ /** signed long long **/
|
|
MAKE_TYPE_SPEC( SIGN_SIGNED, SIZE_LONGLONG, TYPE_INT )
|
|
,NODE_LONGLONG
|
|
,(ATTR_T)ATTR_NONE
|
|
,"long long"
|
|
,NODE_STATE_ALL_SEMANTICS_DONE
|
|
}
|
|
,{ /** unsigned long **/
|
|
MAKE_TYPE_SPEC( SIGN_UNSIGNED, SIZE_LONGLONG, TYPE_INT )
|
|
,NODE_LONGLONG
|
|
,(ATTR_T)ATTR_UNSIGNED
|
|
,"long long"
|
|
,NODE_STATE_ALL_SEMANTICS_DONE
|
|
}
|
|
};
|
|
|
|
ATTR_T ArrayOfBitAttrs[] =
|
|
{
|
|
ATTR_PTR
|
|
,ATTR_UNIQUE
|
|
,ATTR_REF
|
|
,ATTR_IGNORE
|
|
,ATTR_V1_STRING
|
|
,ATTR_LOCAL
|
|
,ATTR_OBJECT
|
|
,ATTR_IDEMPOTENT
|
|
,ATTR_BROADCAST
|
|
,ATTR_MAYBE
|
|
,ATTR_CALLBACK
|
|
,ATTR_DATAGRAM
|
|
,ATTR_NO_LISTEN
|
|
,ATTR_NO_NOCODE
|
|
,ATTR_IN
|
|
,ATTR_OUT
|
|
,ATTR_SHAPE
|
|
,ATTR_UNSIGNED
|
|
,ATTR_DEFAULT
|
|
,ATTR_EXTERN
|
|
,ATTR_STATIC
|
|
,ATTR_AUTOMATIC
|
|
,ATTR_REGISTER
|
|
,ATTR_FAR
|
|
,ATTR_FAR16
|
|
,ATTR_NEAR
|
|
,ATTR_MSCUNALIGNED
|
|
,ATTR_HUGE
|
|
,ATTR_PASCAL
|
|
,ATTR_FORTRAN
|
|
,ATTR_CDECL
|
|
,ATTR_STDCALL
|
|
,ATTR_LOADDS
|
|
,ATTR_SAVEREGS
|
|
,ATTR_FASTCALL
|
|
,ATTR_SEGMENT
|
|
,ATTR_INTERRUPT
|
|
,ATTR_SELF
|
|
,ATTR_EXPORT
|
|
,ATTR_CONST
|
|
,ATTR_VOLATILE
|
|
,ATTR_BASE
|
|
,ATTR_PCODE_NATIVE
|
|
,ATTR_PCODE_CSCONST
|
|
,ATTR_PCODE_SYS
|
|
,ATTR_PCODE_NSYS
|
|
,ATTR_PCODE_UOP
|
|
,ATTR_PCODE_NUOP
|
|
,ATTR_PCODE_TLBX
|
|
,ATTR_PROC_CONST
|
|
,ATTR_C_INLINE
|
|
};
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/*** ParseError ************************************************************
|
|
* Purpose : format and report parsing errors
|
|
* Input :
|
|
* Output :
|
|
* Notes : errors will be reported many times. This is one localised place
|
|
* : for the RpcError Call
|
|
***************************************************************************/
|
|
void
|
|
ParseError(
|
|
STATUS_T Err,
|
|
char * pSuffix )
|
|
{
|
|
char *pFileName;
|
|
short Line;
|
|
short Col;
|
|
char *TempBuf;
|
|
extern char *tokptr_G;
|
|
BOOL flag = (BOOL) ( (*tokptr_G) && !isspace(*tokptr_G) );
|
|
|
|
|
|
pImportCntrl->GetCurrentInputDetails( &pFileName, &Line, &Col);
|
|
|
|
TempBuf = new char [ 512 + 50 ];
|
|
sprintf(TempBuf, " %s %s"
|
|
, (pSuffix == (char *)NULL) ? "" : ":"
|
|
, (pSuffix == (char *)NULL) ? "" : pSuffix);
|
|
#if 0
|
|
sprintf(TempBuf, " %s %s %s %s"
|
|
, flag ? "near" : ""
|
|
, flag ? tokptr_G : ""
|
|
, (pSuffix == (char *)NULL) ? "" : ":"
|
|
, (pSuffix == (char *)NULL) ? "" : pSuffix);
|
|
#endif // 0
|
|
RpcError(pFileName, Line, Err, TempBuf);
|
|
delete TempBuf;
|
|
}
|
|
void
|
|
SyntaxError(
|
|
STATUS_T Err,
|
|
short State )
|
|
{
|
|
|
|
#define NEAR_STRING (" near ")
|
|
#define STRLEN_OF_NEAR_STRING (6)
|
|
|
|
extern char *tokptr_G;
|
|
char * pTemp;
|
|
short len = strlen( tokptr_G );
|
|
char * pBuffer = new char[
|
|
512 +
|
|
STRLEN_OF_NEAR_STRING +
|
|
len + 2 +
|
|
1 ];
|
|
|
|
|
|
|
|
#ifndef NO_GOOD_ERRORS
|
|
|
|
if( Err == BENIGN_SYNTAX_ERROR )
|
|
{
|
|
GetExpectedSyntax( pBuffer, State );
|
|
strcat( pBuffer, NEAR_STRING );
|
|
strcat( pBuffer, "\"" );
|
|
strcat( pBuffer, tokptr_G );
|
|
strcat( pBuffer, "\"" );
|
|
pTemp = pBuffer;
|
|
}
|
|
else
|
|
pTemp = (char *)0;
|
|
|
|
ParseError( Err, pTemp );
|
|
|
|
#else // NO_GOOD_ERRORS
|
|
|
|
strcpy( pBuffer, "syntax error" );
|
|
ParseError( Err, pBuffer );
|
|
|
|
#endif // NO_GOOD_ERRORS
|
|
|
|
delete pBuffer;
|
|
|
|
}
|
|
|
|
/*** BaseTypeSpecAnalysis *************************************************
|
|
* Purpose : to check for valid base type specification
|
|
* Input : pointer to already collected specs, new base type spec
|
|
* Output : modified collected specs
|
|
* Notes :
|
|
***************************************************************************/
|
|
void
|
|
BaseTypeSpecAnalysis(
|
|
struct _type_ana *pType,
|
|
short NewBaseType )
|
|
{
|
|
char TempBuf[ 50 ];
|
|
|
|
if( pType->BaseType == TYPE_PIPE )
|
|
return;
|
|
if( (pType->BaseType != TYPE_UNDEF) && (NewBaseType != TYPE_UNDEF) )
|
|
{
|
|
sprintf(TempBuf,", ignoring %s", GetTypeName(NewBaseType));
|
|
ParseError(BENIGN_SYNTAX_ERROR, TempBuf);
|
|
}
|
|
if(NewBaseType != TYPE_UNDEF)
|
|
pType->BaseType = NewBaseType;
|
|
}
|
|
|
|
/*** SignSpecAnalysis ******************************************************
|
|
* Purpose : to check the sign specification of the type
|
|
* Input : pointer to already collected specs, new sign specs
|
|
* Output : modified collected specs
|
|
* Notes :
|
|
***************************************************************************/
|
|
void
|
|
SignSpecAnalysis(
|
|
struct _type_ana *pType,
|
|
short NewSign)
|
|
{
|
|
char TempBuf[ 50 ];
|
|
if( pType->BaseType == TYPE_PIPE )
|
|
return;
|
|
if( (pType->TypeSign != SIGN_UNDEF) && (NewSign != SIGN_UNDEF) )
|
|
{
|
|
sprintf(TempBuf,", ignoring %s", GetSignName(NewSign));
|
|
ParseError(BENIGN_SYNTAX_ERROR, TempBuf);
|
|
NewSign = pType->TypeSign;
|
|
}
|
|
if(NewSign != SIGN_UNDEF)
|
|
pType->TypeSign = NewSign;
|
|
}
|
|
|
|
/*** SizeSpecAnalysis ******************************************************
|
|
* Purpose : to check the size specification of the type
|
|
* Input : pointer to already collected specs, new size specs
|
|
* Output : modified collected specs
|
|
* Notes :
|
|
***************************************************************************/
|
|
void
|
|
SizeSpecAnalysis(
|
|
struct _type_ana *pType,
|
|
short NewSize)
|
|
{
|
|
char TempBuf[ 50 ];
|
|
|
|
if( pType->BaseType == TYPE_PIPE )
|
|
return;
|
|
if( (pType->TypeSize == SIZE_LONG) && (NewSize == SIZE_LONG ) )
|
|
{
|
|
NewSize = SIZE_LONGLONG;
|
|
}
|
|
else if( (pType->TypeSize != SIZE_UNDEF) && (NewSize != SIZE_UNDEF) )
|
|
{
|
|
sprintf(TempBuf,"ignoring %s", GetSizeName(NewSize));
|
|
ParseError(BENIGN_SYNTAX_ERROR, TempBuf);
|
|
NewSize = pType->TypeSize;
|
|
}
|
|
|
|
if(NewSize != SIZE_UNDEF)
|
|
pType->TypeSize = NewSize;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* routines for the pre_type_db class
|
|
**************************************************************************/
|
|
/*** pre_type_db *********************************************************
|
|
* Purpose : constructor for pre-allocated type data base
|
|
* Input : nothing
|
|
* Output :
|
|
* Notes : inits the prellocated types data base. This routine exist mainly
|
|
* : because static preallocation was giving a problem. If that is
|
|
* : solved, remove this
|
|
**************************************************************************/
|
|
pre_type_db::pre_type_db (void)
|
|
{
|
|
node_skl * pNode;
|
|
int i = 0;
|
|
struct _pre_type * pPreType = &TypeDB[ 0 ];
|
|
struct pre_init * pInitCur = PreInitArray;
|
|
|
|
while( i < PRE_TYPE_DB_SIZE )
|
|
{
|
|
pPreType->TypeSpec = pInitCur->TypeSpec;
|
|
pPreType->pPreAlloc = pNode = new node_base_type(
|
|
pInitCur->NodeType,
|
|
pInitCur->Attr );
|
|
pNode->SetSymName( pInitCur->pSymName );
|
|
pNode->SetNodeState( pInitCur->NodeState );
|
|
pInitCur++;
|
|
pPreType++;
|
|
++i;
|
|
}
|
|
|
|
}
|
|
|
|
/*** GetPreAllocType ******************************************************
|
|
* Purpose : to search for a preallocated base type node, whose type
|
|
* : spec is provided
|
|
* Input : pointer to the resultant base node
|
|
* Output : STATUS_OK if all is well, error otherwise
|
|
* Notes :
|
|
**************************************************************************/
|
|
STATUS_T
|
|
pre_type_db::GetPreAllocType(
|
|
node_skl ** ppNode,
|
|
unsigned short TypeSpec )
|
|
{
|
|
int i = 0;
|
|
|
|
if( GET_TYPE( TypeSpec ) == TYPE_PIPE )
|
|
{
|
|
(*ppNode) = pErrorTypeNode;
|
|
return STATUS_OK;
|
|
}
|
|
|
|
while(i < sizeof(TypeDB) / sizeof(struct _pre_type) )
|
|
{
|
|
if( TypeDB[i].TypeSpec == TypeSpec )
|
|
{
|
|
(*ppNode) = TypeDB[i].pPreAlloc;
|
|
return STATUS_OK;
|
|
}
|
|
++i;
|
|
}
|
|
return SYNTAX_ERROR;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* pre allocated , bit attributes
|
|
***************************************************************************/
|
|
|
|
void
|
|
PreAllocateBitAttrs()
|
|
{
|
|
|
|
ATTR_T * pAttrValue;
|
|
short i;
|
|
|
|
/**
|
|
** Pre allocate t
|
|
**/
|
|
|
|
pPreAllocatedBitAttrDict = new idict
|
|
(sizeof(ArrayOfBitAttrs)/sizeof(ATTR_T), 1);
|
|
|
|
pAttrValue = ArrayOfBitAttrs;
|
|
|
|
for( i = 0;
|
|
|
|
i < sizeof( ArrayOfBitAttrs ) / sizeof( ATTR_T );
|
|
|
|
i++, pAttrValue++
|
|
)
|
|
{
|
|
pPreAllocatedBitAttrDict->AddElement(
|
|
(IDICTELEMENT) new battr( *pAttrValue ) );
|
|
|
|
}
|
|
}
|
|
|
|
battr *
|
|
GetPreAllocatedBitAttr(
|
|
ATTR_T At )
|
|
{
|
|
short i;
|
|
battr * pBAttr;
|
|
|
|
assert( pPreAllocatedBitAttrDict != (idict *)NULL );
|
|
|
|
for( i = 0;
|
|
|
|
i < sizeof( ArrayOfBitAttrs ) / sizeof( ATTR_T );
|
|
|
|
i++
|
|
)
|
|
{
|
|
if( pBAttr = ( battr * )
|
|
pPreAllocatedBitAttrDict->GetElement( (IDICTKEY)i ) )
|
|
{
|
|
if( pBAttr->GetAttrID() == At )
|
|
return pBAttr;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
assert( FALSE );
|
|
|
|
return ( battr * )pErrorAttrNode;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* nested symbol table access support
|
|
***************************************************************************/
|
|
nsa::nsa( void )
|
|
{
|
|
SymTable * pSymTable = new SymTable;
|
|
CurrentLevel = 0;
|
|
Insert( (void *)pSymTable );
|
|
}
|
|
STATUS_T
|
|
nsa::PushSymLevel(
|
|
SymTable **ppSymTable )
|
|
{
|
|
STATUS_T Status;
|
|
SymTable *pSymTable = new SymTable;
|
|
|
|
CurrentLevel++;
|
|
Status = Insert( (void *)pSymTable);
|
|
Advance();
|
|
*ppSymTable = pSymTable;
|
|
return Status;
|
|
}
|
|
STATUS_T
|
|
nsa::PopSymLevel(
|
|
SymTable **ppSymTable )
|
|
{
|
|
if(CurrentLevel == 0)
|
|
return I_ERR_SYMTABLE_UNDERFLOW;
|
|
CurrentLevel--;
|
|
Remove();
|
|
return GetCurrent( (void **)ppSymTable );
|
|
}
|
|
short
|
|
nsa::GetCurrentLevel( void )
|
|
{
|
|
return CurrentLevel;
|
|
}
|
|
SymTable *
|
|
nsa::GetCurrentSymbolTable()
|
|
{
|
|
SymTable *pSymbolTable;
|
|
GetCurrent( (void **)&pSymbolTable );
|
|
return pSymbolTable;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* nested symbol table access support
|
|
***************************************************************************/
|
|
void
|
|
IINFODICT::StartNewInterface()
|
|
{
|
|
IINFO * pInfo = new IINFO;
|
|
|
|
pInfo->fLocal = FALSE;
|
|
pInfo->InterfacePtrAttribute = ATTR_NONE;
|
|
pInfo->pInterfaceName = "";
|
|
pInfo->CurrentTagNumber = 1;
|
|
pInfo->fPtrDefErrorReported = 0;
|
|
pInfo->fPtrWarningIssued = FALSE;
|
|
|
|
Push( (IDICTELEMENT) pInfo );
|
|
|
|
}
|
|
|
|
BOOL
|
|
IINFODICT::IsPtrWarningIssued()
|
|
{
|
|
IINFO * pInfo = (IINFO *)GetTop();
|
|
return pInfo->fPtrWarningIssued;
|
|
}
|
|
|
|
void
|
|
IINFODICT::SetPtrWarningIssued()
|
|
{
|
|
IINFO * pInfo = (IINFO *)GetTop();
|
|
pInfo->fPtrWarningIssued = TRUE;
|
|
}
|
|
|
|
void
|
|
IINFODICT::EndNewInterface()
|
|
{
|
|
IINFO * pInfo = (IINFO *)GetTop();
|
|
|
|
delete pInfo;
|
|
Pop();
|
|
|
|
}
|
|
void
|
|
IINFODICT::SetInterfacePtrAttribute(
|
|
ATTR_T A )
|
|
{
|
|
IINFO * pInfo = (IINFO *)GetTop();
|
|
pInfo->InterfacePtrAttribute = A;
|
|
if( ImportLevel == 0 ) BaseInterfacePtrAttribute = A;
|
|
}
|
|
void
|
|
IINFODICT::SetInterfaceLocal()
|
|
{
|
|
IINFO * pInfo = (IINFO *)GetTop();
|
|
pInfo->fLocal = TRUE;
|
|
if( ImportLevel == 0 ) fBaseLocal = TRUE;
|
|
}
|
|
void
|
|
IINFODICT::SetInterfaceName(
|
|
char * p )
|
|
{
|
|
IINFO * pInfo = (IINFO *)GetTop();
|
|
pInfo->pInterfaceName = p;
|
|
if( ImportLevel == 0 ) pBaseInterfaceName = p;
|
|
}
|
|
void
|
|
IINFODICT::IncrementCurrentTagNumber()
|
|
{
|
|
IINFO * pInfo = (IINFO *)GetTop();
|
|
pInfo->CurrentTagNumber++;
|
|
}
|
|
ATTR_T
|
|
IINFODICT::GetInterfacePtrAttribute()
|
|
{
|
|
IINFO * pInfo = (IINFO *)GetTop();
|
|
return pInfo->InterfacePtrAttribute;
|
|
}
|
|
ATTR_T
|
|
IINFODICT::GetBaseInterfacePtrAttribute()
|
|
{
|
|
return BaseInterfacePtrAttribute;
|
|
}
|
|
BOOL
|
|
IINFODICT::IsInterfaceLocal()
|
|
{
|
|
IINFO * pInfo = (IINFO *)GetTop();
|
|
return pInfo->fLocal;
|
|
}
|
|
char *
|
|
IINFODICT::GetInterfaceName()
|
|
{
|
|
IINFO * pInfo = (IINFO *)GetTop();
|
|
return pInfo->pInterfaceName;
|
|
}
|
|
short
|
|
IINFODICT::GetCurrentTagNumber()
|
|
{
|
|
IINFO * pInfo = (IINFO *)GetTop();
|
|
return pInfo->CurrentTagNumber;
|
|
}
|
|
void
|
|
IINFODICT::SetPtrDefErrorReported()
|
|
{
|
|
IINFO * pInfo = (IINFO *) GetTop();
|
|
pInfo->fPtrDefErrorReported = 1;
|
|
}
|
|
BOOL
|
|
IINFODICT::IsPtrDefErrorReported()
|
|
{
|
|
IINFO * pInfo = (IINFO *) GetTop();
|
|
return (BOOL) (pInfo->fPtrDefErrorReported == 1);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* utility functions
|
|
***************************************************************************/
|
|
char *
|
|
GetSizeName(
|
|
short Size )
|
|
{
|
|
char *p;
|
|
switch(Size)
|
|
{
|
|
case SIZE_CHAR: p = "\"char\""; break;
|
|
case SIZE_SHORT: p = "\"short\""; break;
|
|
case SIZE_LONG: p = "\"long\""; break;
|
|
case SIZE_HYPER: p = "\"hyper\""; break;
|
|
case SIZE_SMALL: p = "\"small\""; break;
|
|
default: p = ""; break;
|
|
}
|
|
return p;
|
|
}
|
|
char *
|
|
GetSignName(
|
|
short Sign )
|
|
{
|
|
char *p;
|
|
switch(Sign)
|
|
{
|
|
case SIGN_SIGNED: p = "\"signed\""; break;
|
|
case SIGN_UNSIGNED: p = "\"unsigned\""; break;
|
|
default: p = ""; break;
|
|
}
|
|
return p;
|
|
}
|
|
char *
|
|
GetTypeName(
|
|
short Type )
|
|
{
|
|
char *p;
|
|
switch(Type)
|
|
{
|
|
case TYPE_INT: p = "\"int\""; break;
|
|
case TYPE_FLOAT: p = "\"float\""; break;
|
|
case TYPE_DOUBLE: p = "\"double\""; break;
|
|
case TYPE_VOID: p = "\"void\""; break;
|
|
case TYPE_BOOLEAN: p = "\"boolean\""; break;
|
|
case TYPE_HANDLE_T: p = "\"handle_t\""; break;
|
|
default: p = ""; break;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
STATUS_T
|
|
GetBaseTypeNode(
|
|
node_skl ** ppNode,
|
|
short TypeSign,
|
|
short TypeSize,
|
|
short BaseType)
|
|
{
|
|
|
|
STATUS_T uStatus = STATUS_OK;
|
|
|
|
if( pPreAllocTypes->GetPreAllocType(
|
|
ppNode,
|
|
MAKE_TYPE_SPEC(TypeSign,TypeSize,BaseType)) != STATUS_OK)
|
|
{
|
|
// this should never happen
|
|
assert( FALSE );
|
|
*ppNode = (node_skl *)new node_error;
|
|
}
|
|
return uStatus;
|
|
|
|
}
|
|
|
|
#define TEMPNAME ("__MIDL_")
|
|
#define TEMP_NAME_LENGTH (7)
|
|
#define LENGTH_OF_1_UNDERSCORE (1)
|
|
|
|
char *
|
|
GenTempName()
|
|
{
|
|
static short NameCounter = 0;
|
|
char TempBuf[ TEMP_NAME_LENGTH + 4 + 1 ];
|
|
sprintf(TempBuf, "%s%.4d", TEMPNAME, NameCounter++);
|
|
return pMidlLexTable->LexInsert( TempBuf );
|
|
}
|
|
|
|
char *
|
|
GenCompName()
|
|
{
|
|
char * pCurrentInterfaceName;
|
|
short Length;
|
|
char * pBuffer;
|
|
char * pTemp;
|
|
short CurrentTagNumber;
|
|
|
|
pCurrentInterfaceName = pInterfaceInfoDict->GetInterfaceName();
|
|
Length = strlen(pCurrentInterfaceName);
|
|
pBuffer = new char[
|
|
TEMP_NAME_LENGTH + // __MIDL_
|
|
Length + // intface name
|
|
LENGTH_OF_1_UNDERSCORE + // _
|
|
4 + // temp number
|
|
1 ]; // term. zero.
|
|
|
|
CurrentTagNumber = pInterfaceInfoDict->GetCurrentTagNumber();
|
|
|
|
sprintf( pBuffer, "%s%s_%.4d", TEMPNAME, pCurrentInterfaceName, CurrentTagNumber );
|
|
|
|
pInterfaceInfoDict->IncrementCurrentTagNumber();
|
|
|
|
pTemp = pMidlLexTable->LexInsert( pBuffer );
|
|
delete pBuffer;
|
|
return pTemp;
|
|
|
|
}
|
|
|
|
BOOL
|
|
IsTempName(
|
|
char *pName )
|
|
{
|
|
return !(strncmp( pName, TEMPNAME , TEMP_NAME_LENGTH ) );
|
|
}
|
|
|
|
void
|
|
ApplyAttributes(
|
|
node_skl * pNode,
|
|
type_node_list * pTNList )
|
|
{
|
|
node_base_attr * pAttrNode;
|
|
|
|
if( pTNList )
|
|
{
|
|
pTNList->Sort();
|
|
pTNList->Init();
|
|
|
|
pNode->SetAttribute(pTNList);
|
|
|
|
if( pTNList->GetCount())
|
|
{
|
|
pTNList->Init();
|
|
while( pTNList->GetPeer( (node_skl **)&pAttrNode ) == STATUS_OK )
|
|
{
|
|
ParseError(INAPPLICABLE_ATTRIBUTE, pAttrNode->GetNodeNameString());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
CopyNode(
|
|
node_skl * pDest,
|
|
node_skl * pSrc )
|
|
{
|
|
char * pName;
|
|
|
|
pName = pSrc->GetSymName();
|
|
pDest->SetSymName( pName ? pName : GenTempName() );
|
|
pDest->SetBasicType( pSrc->GetBasicType() );
|
|
|
|
delete pSrc;
|
|
}
|
|
|
|
/****************************************************************************
|
|
This routine exists to share code for setting up the field attribute nodes
|
|
****************************************************************************/
|
|
type_node_list *
|
|
GenerateFieldAttribute(
|
|
NODE_T NodeType,
|
|
expr_list * pExprList )
|
|
{
|
|
node_base_attr * pAttr;
|
|
expr_node * pExpr;
|
|
type_node_list * pTNList = new type_node_list;
|
|
|
|
/**
|
|
** we delibrately dont set the bits in the summary attribute 'cause
|
|
** these bits will get set in the set attribute anyways for the
|
|
** field attributes
|
|
**/
|
|
|
|
if(pExprList != (expr_list *)NULL)
|
|
{
|
|
pExprList->Init();
|
|
while( pExprList->GetNext( (void **)&pExpr ) == STATUS_OK)
|
|
{
|
|
switch(NodeType)
|
|
{
|
|
case NODE_FIRST:
|
|
pAttr = (node_base_attr *)new node_first_is( pExpr );
|
|
break;
|
|
case NODE_IID:
|
|
pAttr = (node_base_attr *)new node_iid_is( pExpr );
|
|
break;
|
|
case NODE_LAST:
|
|
pAttr = (node_base_attr *)new node_last_is( pExpr );
|
|
break;
|
|
case NODE_LENGTH:
|
|
pAttr = (node_base_attr *)new node_length_is( pExpr );
|
|
break;
|
|
case NODE_SIZE:
|
|
pAttr = (node_base_attr *)new node_size_is( pExpr );
|
|
break;
|
|
case NODE_MIN:
|
|
pAttr = (node_base_attr *)new node_min_is( pExpr );
|
|
break;
|
|
case NODE_MAX:
|
|
pAttr = (node_base_attr *)new node_max_is( pExpr );
|
|
break;
|
|
}
|
|
pTNList->SetPeer( (node_skl *)pAttr );
|
|
}
|
|
}
|
|
return pTNList;
|
|
}
|
|
/****************************************************************************
|
|
SearchTag:
|
|
This routine provides a means of searching the global symbol space for
|
|
struct/union tags, and enums. These share the same name space but we want to
|
|
keep the symbol table identity of enums, struct tags etc separate. so
|
|
we need to search for all of these separately when verifying that a tag
|
|
has really not been seen before.
|
|
|
|
This routine returns:
|
|
1. (node_skl *)NULL if NO struct/union/enum was defined by that name
|
|
2. node_skl * if the a definition was found for what you are looking
|
|
for.
|
|
3. (node_skl *) error type node if a definition was found, but it is
|
|
not what you are looking for.
|
|
****************************************************************************/
|
|
node_skl *
|
|
SearchTag(
|
|
char * pName,
|
|
NAME_T Tag )
|
|
{
|
|
node_skl * pNode;
|
|
NAME_T MyTag;
|
|
SymKey SKey( pName, MyTag = NAME_TAG );
|
|
|
|
/**
|
|
** Has it been declared as a struct ?
|
|
**/
|
|
|
|
if( !(pNode = pBaseSymTbl->SymSearch(SKey) ) )
|
|
{
|
|
|
|
/**
|
|
** not a tag - maybe enum / union
|
|
**/
|
|
|
|
SKey.SetKind( MyTag = NAME_ENUM );
|
|
|
|
if( !(pNode = pBaseSymTbl->SymSearch(SKey) ) )
|
|
{
|
|
|
|
/**
|
|
** not a enum maybe union
|
|
**/
|
|
|
|
SKey.SetKind( MyTag = NAME_UNION );
|
|
|
|
if( !(pNode = pBaseSymTbl->SymSearch(SKey) ) )
|
|
return (node_skl *)NULL;
|
|
}
|
|
}
|
|
|
|
/**
|
|
** search was sucessful. Check whether this was what you were looking
|
|
** for. If it is , it means we found a definition of the symbol. If not
|
|
** then we found a definition all right, but it is of a different entity.
|
|
** The routine can find this out by verifying that the typenode returned
|
|
** was an error type node or not
|
|
**/
|
|
|
|
return (MyTag == Tag ) ? pNode : pErrorTypeNode;
|
|
}
|
|
|
|
/****************************************************************************
|
|
SelectiveSemanticsAndEnGraph:
|
|
This routine send out the semantics message to declaration passed
|
|
in, applies the attributes passed in, and adds a component to the list
|
|
of interface components.
|
|
|
|
Note this routine will set the NODE_STATE_IMPORT_OFF on interface components
|
|
to indicate to the back end that this type was defined under the import
|
|
off situation
|
|
****************************************************************************/
|
|
void
|
|
SelectiveSemanticsAndEnGraph(
|
|
type_node_list ** ppInterfaceCompList,
|
|
type_node_list * pAttributeSet,
|
|
type_node_list * pDeclarations,
|
|
BOOL fInterfaceLocal,
|
|
BOOL fImportOn )
|
|
{
|
|
|
|
node_skl * pNode;
|
|
type_node_list * pAttrList;
|
|
type_node_list * pInterfaceCompList = (type_node_list *)NULL;
|
|
BadUseInfo BU;
|
|
|
|
UNUSED( fInterfaceLocal );
|
|
/**
|
|
** prepare to fail.
|
|
**/
|
|
|
|
pInterfaceCompList = (type_node_list *)NULL;
|
|
|
|
/**
|
|
** if there are declarations, then ,for each of the declarations,
|
|
** apply attributes
|
|
**/
|
|
|
|
if( pDeclarations )
|
|
{
|
|
BOOL fInsert;
|
|
BOOL fDoSemantics;
|
|
|
|
pDeclarations->Init();
|
|
|
|
while( pDeclarations->GetPeer( &pNode ) == STATUS_OK )
|
|
{
|
|
|
|
/**
|
|
** if pragma import off is specified, then stamp the typenode
|
|
**/
|
|
|
|
if( fImportOn == TRUE )
|
|
pNode->SetNodeState( NODE_STATE_PRAGMA_IMPORT_ON );
|
|
|
|
/**
|
|
** Apply Attributes if any. Remember, we must clone the attribute
|
|
** list.
|
|
**/
|
|
|
|
if( pAttributeSet )
|
|
{
|
|
pAttrList = new type_node_list;
|
|
|
|
pAttrList->Clone( pAttributeSet );
|
|
ApplyAttributes( pNode, pAttrList );
|
|
|
|
delete pAttrList;
|
|
}
|
|
/**
|
|
** if the node is a operation node (proc), then insert into the
|
|
** type graph only if importlevel is 0 and the pragma import is off
|
|
** Do semantics only if the above is true AND the interface is
|
|
** not local and the proc itself is not local
|
|
**/
|
|
|
|
if( (pNode->NodeKind() == NODE_PROC) && !fObject )
|
|
{
|
|
|
|
fInsert = (
|
|
(((node_proc *)pNode)->GetImportLevel() == 0) &&
|
|
( fImportOn == FALSE )
|
|
);
|
|
|
|
// fDoSemantics = fInsert &&
|
|
// !pNode->FInSummary( ATTR_LOCAL ) &&
|
|
// !fInterfaceLocal;
|
|
fDoSemantics = TRUE;
|
|
|
|
}
|
|
else
|
|
{
|
|
fDoSemantics = TRUE;
|
|
fInsert = TRUE;
|
|
}
|
|
|
|
if( fDoSemantics )
|
|
pNode->SCheck( &BU );
|
|
else
|
|
{
|
|
|
|
/**
|
|
** make believe that the semantics and the post semantics
|
|
** have been done
|
|
**/
|
|
pNode->SetSemanticsDone();
|
|
pNode->SetPostSemanticsDone();
|
|
|
|
}
|
|
|
|
if( fInsert )
|
|
{
|
|
if( ! pInterfaceCompList )
|
|
{
|
|
pInterfaceCompList = new type_node_list;
|
|
}
|
|
pInterfaceCompList->SetPeer( pNode );
|
|
}
|
|
|
|
}
|
|
delete pDeclarations;
|
|
}
|
|
*ppInterfaceCompList = pInterfaceCompList;
|
|
}
|
|
|
|
/****************************************************************************
|
|
SetPredefinedTypes:
|
|
Set up predefined types for the midl compiler. The predefined types
|
|
are error_status_t and wchar_t( the latter dependent on compile mode )
|
|
****************************************************************************/
|
|
void
|
|
SetPredefinedTypes()
|
|
{
|
|
|
|
node_def * pDef = new node_def;
|
|
node_skl * pNew = new node_e_status_t;
|
|
char * pName;
|
|
|
|
pDef->SetSymName( pName = pNew->GetSymName() );
|
|
pDef->SetBasicType( pNew );
|
|
pDef->SetEdgeType( EDGE_DEF );
|
|
pDef->SetSemanticsDone();
|
|
pDef->SetPostSemanticsDone();
|
|
|
|
// the typedef of error_status_t in the symbol table
|
|
|
|
SymKey SKey( pName, NAME_DEF);
|
|
pBaseSymTbl->SymInsert(SKey, (SymTable *)NULL, pDef );
|
|
|
|
//
|
|
// we always predefine wchar_t and report the error to the user. If
|
|
// we dont enter wchar_t in the predefined types, then we get all
|
|
// kinds of syntax and error recovery errors which could be confusing
|
|
// in this context. We therefore explicitly give an error on wchar_t.
|
|
//
|
|
|
|
pDef = new node_def;
|
|
pNew = new node_wchar_t;
|
|
pDef->SetSymName( pName = pNew->GetSymName() );
|
|
pDef->SetBasicType( pNew );
|
|
pDef->SetEdgeType( EDGE_DEF );
|
|
pDef->SetSemanticsDone();
|
|
pDef->SetPostSemanticsDone();
|
|
|
|
// the typedef of wchar_t in the symbol table
|
|
|
|
SKey.SetString( pName );
|
|
pBaseSymTbl->SymInsert(SKey, (SymTable *)NULL, pDef );
|
|
|
|
}
|
|
|
|
//For each interface definition, we create a special typedef node
|
|
//to support interface pointers.
|
|
|
|
//The [iid_is] attribute on the
|
|
//typedef node identifies it as an interface.
|
|
|
|
node_skl *
|
|
SetHppPredefinedTypes(
|
|
char * pInterfaceName)
|
|
{
|
|
char *pszIdentifier;
|
|
SymKey SKey( pInterfaceName, NAME_DEF);
|
|
node_def * pDef;
|
|
node_skl *pNew;
|
|
node_iid_is *piid;
|
|
type_node_list *pAttrList;
|
|
expr_node *pExpr;
|
|
|
|
|
|
GetBaseTypeNode(&pNew, SIGN_UNSIGNED, SIZE_LONG, TYPE_INT);
|
|
|
|
pDef = new node_def( pInterfaceName );
|
|
pDef->SetBasicType( pNew );
|
|
pDef->SetEdgeType( EDGE_USE );
|
|
|
|
//Set the [iid_is] attribute
|
|
pszIdentifier = new char [ strlen(pInterfaceName) + 5];
|
|
strcpy(pszIdentifier, "IID_");
|
|
strcat(pszIdentifier, pInterfaceName);
|
|
pExpr = new expr_variable((char *) pszIdentifier);
|
|
piid = new node_iid_is(pExpr);
|
|
pAttrList = new type_node_list((node_skl *) piid);
|
|
ApplyAttributes(pDef, pAttrList);
|
|
delete pAttrList;
|
|
|
|
|
|
// Add the interface name to the symbol table
|
|
pBaseSymTbl->SymInsert(SKey, (SymTable *)NULL, pDef );
|
|
|
|
return pDef;
|
|
|
|
}
|
|
|
|
|
|
node_skl *
|
|
CopyBaseType(
|
|
node_skl * pNode )
|
|
{
|
|
|
|
node_base_type * pBaseType;
|
|
ATTR_T Attr = ATTR_NONE;
|
|
|
|
if( pNode->FInSummary( ATTR_UNSIGNED ) )
|
|
Attr = ATTR_UNSIGNED;
|
|
|
|
pBaseType = new node_base_type( pNode->NodeKind(), Attr );
|
|
pBaseType->SetNodeState( pNode->GetNodeState() );
|
|
pBaseType->SetSymName( pNode->GetSymName() );
|
|
return pBaseType;
|
|
}
|
|
|
|
BOOL
|
|
IsValidSizeOfType(
|
|
node_skl * pNode )
|
|
{
|
|
|
|
NODE_T NT = pNode->NodeKind();
|
|
|
|
if( IS_BASE_TYPE_NODE( NT ) || (NT == NODE_WCHAR_T) )
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
switch( NT )
|
|
{
|
|
case NODE_POINTER:
|
|
case NODE_ERROR_STATUS_T:
|
|
case NODE_ENUM:
|
|
case NODE_UNION:
|
|
return TRUE;
|
|
case NODE_STRUCT:
|
|
case NODE_ARRAY:
|
|
return(!( (pNode->GetNodeState() & NODE_STATE_CONF_ARRAY ) ==
|
|
NODE_STATE_CONF_ARRAY ));
|
|
case NODE_DEF:
|
|
case NODE_ID:
|
|
return IsValidSizeOfType( pNode->GetBasicType() );
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// We check for a proc/typedef/member/param/tag/enum/label name already defined
|
|
// as an identifier. Only if the identifier is one which will be turned into
|
|
// a #define, do we report an error. However, it is not worth it to check if
|
|
// an identifier is used as a name because in any case we will not be able to
|
|
// check for clashes with field / param names since they are at a lower than
|
|
// global, symbol table scope. Generally checking if the name of a member etc
|
|
// is already defined as an id which will be turned into a #define should be
|
|
// enough.
|
|
//
|
|
|
|
void
|
|
CheckGlobalNamesClash(
|
|
SymKey SKeyOfSymbolBeingDefined )
|
|
{
|
|
NAME_T NT = SKeyOfSymbolBeingDefined.GetKind();
|
|
char * pName = SKeyOfSymbolBeingDefined.GetString();
|
|
SymKey SKey;
|
|
|
|
SKey.SetString( pName );
|
|
|
|
switch( NT )
|
|
{
|
|
case NAME_PROC:
|
|
case NAME_MEMBER:
|
|
case NAME_TAG:
|
|
case NAME_DEF:
|
|
case NAME_LABEL:
|
|
case NAME_ENUM:
|
|
|
|
node_id * pID;
|
|
|
|
SKey.SetKind( NAME_ID );
|
|
|
|
if( pID = (node_id *) pBaseSymTbl->SymSearch( SKey ) )
|
|
{
|
|
BOOL fWillBeAHashDefine = !pID->FInSummary( ATTR_EXTERN ) &&
|
|
!pID->FInSummary( ATTR_STATIC ) &&
|
|
pID->GetInitList();
|
|
if( fWillBeAHashDefine )
|
|
ParseError( NAME_ALREADY_USED, pName );
|
|
}
|
|
break;
|
|
|
|
case NAME_ID:
|
|
|
|
#if 0
|
|
SKey.SetKind( NAME_PROC );
|
|
if( !pBaseSymTbl->SymSearch( SKey ) )
|
|
{
|
|
SKey.SetKind( NAME_TAG );
|
|
if( !pBaseSymTbl->SymSearch( SKey ) )
|
|
{
|
|
SKey.SetKind( NAME_DEF );
|
|
if( !pBaseSymTbl->SymSearch( SKey ) )
|
|
{
|
|
SKey.SetKind( NAME_LABEL );
|
|
if( !pBaseSymTbl->SymSearch( SKey ) )
|
|
{
|
|
SKey.SetKind( NAME_ENUM );
|
|
if( !pBaseSymTbl->SymSearch( SKey ) )
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
ParseError( NAME_CLASH_WITH_CONST_ID, pName );
|
|
break;
|
|
#endif // 0
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// checks for the special typedef node case when the only construct allowed is
|
|
// when context_handle is applied to an unknown type.
|
|
//
|
|
|
|
void
|
|
CheckSpecialForwardTypedef(
|
|
node_skl * pTypedefNode,
|
|
node_skl * pType,
|
|
type_node_list * pAttrList )
|
|
{
|
|
|
|
short fContextHandleCount;
|
|
short fOtherAttributeCount;
|
|
node_base_attr * pAttrNode;
|
|
char Buffer[ 256 ];
|
|
char * pName;
|
|
node_forward * pForward;
|
|
NAME_T T;
|
|
char * pDummy;
|
|
|
|
//
|
|
// if the type is not a forward node, just return. Or if the type is
|
|
// not a forward type name return. We want to barf on forward
|
|
// declarations of these forms only:
|
|
//
|
|
// typedef FOO ID;
|
|
// typedef FOO * ID;
|
|
//
|
|
|
|
if( (pForward = ((node_forward *)pType))->NodeKind() != NODE_FORWARD )
|
|
return;
|
|
|
|
pForward->GetSymDetails( &T, &pDummy );
|
|
|
|
if( T != NAME_DEF )
|
|
return;
|
|
|
|
pName = pTypedefNode->GetSymName();
|
|
|
|
fContextHandleCount = 0;
|
|
fOtherAttributeCount= 0;
|
|
|
|
//
|
|
// then only attribute in the attribute list must be context_handle,
|
|
// and NOTHING else.
|
|
//
|
|
|
|
if( pAttrList )
|
|
{
|
|
pAttrList->Init();
|
|
|
|
while( pAttrList->GetPeer( (node_skl **)&pAttrNode ) == STATUS_OK )
|
|
{
|
|
if( pAttrNode->GetAttrID() == ATTR_CONTEXT )
|
|
fContextHandleCount++;
|
|
else
|
|
fOtherAttributeCount++;
|
|
}
|
|
|
|
//
|
|
// the only case allowed is when context_handle is applied and
|
|
// nothing else is applied.
|
|
|
|
if( fContextHandleCount && !fOtherAttributeCount )
|
|
return;
|
|
|
|
}
|
|
//
|
|
// report it as a syntax error.
|
|
//
|
|
|
|
sprintf( Buffer, "expecting a type specification near %s", pName );
|
|
ParseError( BENIGN_SYNTAX_ERROR, Buffer );
|
|
}
|