Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

6285 lines
199 KiB

/*****************************************************************************/
/** Microsoft LAN Manager **/
/** Copyright(c) Microsoft Corp., 1987-1990 **/
/*****************************************************************************/
/*****************************************************************************
File : grammar.y
Title : the midl grammar file
:
Description: contains the syntactic and semantic handling of the
: idl file
History :
08-Aug-1991 VibhasC Create
15-Sep-1993 GregJen Rewrite for MIDL 2.0
*****************************************************************************/
%{
/****************************************************************************
*** local defines
***************************************************************************/
#define pascal
#define FARDATA
#define NEARDATA
#define FARCODE
#define NEARCODE
#define NEARSWAP
#define YYFARDATA
#define PASCAL pascal
#define CDECL
#define VOID void
#define CONST const
#define GLOBAL
#define YYSTYPE lextype_t
#define YYNEAR NEARCODE
#define YYPASCAL PASCAL
#define YYPRINT printf
#define YYSTATIC static
#define YYCONST static const
#define YYLEX yylex
#define YYPARSER yyparse
#ifdef gajdebug3
#define YYDEBUG
#endif
#define IS_CUR_INTERFACE_LOCAL() ( \
(BOOL) (pInterfaceInfoDict->IsInterfaceLocal()) )
/****************************************************************************
*** include files
***************************************************************************/
#include "nulldefs.h"
extern "C" {
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
int yyparse();
}
#include "allnodes.hxx"
#include "lexutils.hxx"
#include "gramutil.hxx"
#include "idict.hxx"
#include "filehndl.hxx"
#include "cmdana.hxx"
#include "control.hxx"
#include "tlgen.hxx"
extern "C" {
#include "lex.h"
extern char * KeywordToString( token_t );
}
/***************************************************************************
* local data
**************************************************************************/
BOOL fBaseImported = FALSE;
BOOL fOdlBaseImported = FALSE;
BOOL fLibrary = FALSE;
/***************************************************************************
* external data
**************************************************************************/
extern CMD_ARG * pCommand;
extern node_error * pErrorTypeNode;
extern node_e_attr * pErrorAttrNode;
extern SymTable * pBaseSymTbl;
extern SymTable * pCurSymTbl;
extern nsa * pSymTblMgr;
extern short ImportLevel;
extern BOOL fTypeGraphInited;
extern BOOL fPragmaImportOn;
extern CCONTROL * pCompiler;
extern node_source * pSourceNode;
extern NFA_INFO * pImportCntrl;
extern PASS_1 * pPass1;
extern IINFODICT * pInterfaceInfoDict;
extern unsigned short LexContext;
extern BOOL fRedundantImport;
extern node_skl * pBaseImplicitHandle;
extern unsigned short CurrentZp;
extern node_pragma_pack * pPackStack;
/***************************************************************************
* external functions
**************************************************************************/
extern void yyunlex( token_t );
extern BOOL IsTempName( char * );
extern char * GenTempName();
extern char * GenIntfName();
extern char * GenCompName();
extern void CopyNode( node_skl *, node_skl * );
extern STATUS_T GetBaseTypeNode( node_skl **, short, short, short);
extern ATTRLIST GenerateFieldAttribute( ATTR_T, expr_list *);
extern node_skl * SearchTag( char *, NAME_T );
extern void SyntaxError( STATUS_T, short );
extern int PossibleMissingToken( short, short );
extern char * MakeNewStringWithProperQuoting( char * );
extern void CheckGlobalNamesClash( SymKey );
extern void CheckSpecialForwardTypedef( node_skl *, node_skl *, type_node_list *);
extern void PushZpStack( node_pragma_pack * & PackStack,
unsigned short & CurrentZp );
extern void PopZpStack( node_pragma_pack * & PackStack,
unsigned short & CurrentZp );
/***************************************************************************
* local data
**************************************************************************/
/***************************************************************************
* local defines
**************************************************************************/
#define YY_CATCH(x)
#define DEFINE_STRING "#define"
#define LEN_DEFINE (7)
%}
/****************************************************************************/
%start RpcProg
%token KWINTERFACE
%token KWCLASS
%token KWEXESERVER
%token KWDLLSERVER
%token KWIMPORT
%token KWIMPORTIDLBASE
%token KWIMPORTODLBASE
%token KWCPPQUOTE
%token KWCPRAGMA
%token KWCPRAGMAPACK
%token KWMPRAGMAIMPORT
%token KWMPRAGMAECHO
%token KWMPRAGMAIMPORTCLNTAUX
%token KWMPRAGMAIMPORTSRVRAUX
%token TYPENAME
%token LIBNAME
%token KWVOID
%token KWUNSIGNED
%token KWSIGNED
%token KWFLOAT
%token KWDOUBLE
%token KWINT
%token KWBYTE
%token KWCHAR
%token KWSMALL
%token KWLONG
%token KWSHORT
%token KWHYPER
%token KWINT64
%token KWSTRUCT
%token KWUNION
%token KWENUM
%token KWSHORTENUM
%token KWLONGENUM
%token KWCONST
%token KWVOLATILE
%token KW_C_INLINE
%token KWTYPEDEF
%token KWEXTERN
%token KWSTATIC
%token KWAUTO
%token KWREGISTER
%token KWERRORSTATUST
%token KWBOOLEAN
%token KWISOLATIN1
%token KWPRIVATECHAR8
%token KWISOMULTILINGUAL
%token KWPRIVATECHAR16
%token KWISOUCS
%token KWPIPE
%token KWSWITCH
%token KWCASE
%token KWDEFAULT
%token KWUUID
%token KWVERSION
%token KWOPAQUE
%token KWSTRING
%token KWBSTRING
%token KWIN
%token KWOUT
%token KWIIDIS
%token KWFIRSTIS
%token KWLASTIS
%token KWMAXIS
%token KWMINIS
%token KWLENGTHIS
%token KWSIZEIS
/* start of ODL key words */
%token KWID
%token KWHC /* helpcontext attribute */
%token KWHSC /* helpstring context attribute */
%token KWLCID
%token KWDLLNAME
%token KWHELPSTR
%token KWHELPFILE
%token KWENTRY
%token KWPROPGET
%token KWPROPPUT
%token KWPROPPUTREF
%token KWOPTIONAL
%token KWVARARG
%token KWAPPOBJECT
%token KWRESTRICTED
%token KWPUBLIC
%token KWREADONLY
%token KWODL
%token KWSOURCE
%token KWBINDABLE
%token KWREQUESTEDIT
%token KWDISPLAYBIND
%token KWDEFAULTBIND
%token KWLICENSED
%token KWPREDECLID
%token KWHIDDEN
%token KWRETVAL
%token KWCONTROL
%token KWDUAL
%token KWNONEXTENSIBLE
%token KWNONCREATABLE
%token KWOLEAUTOMATION
%token KWLIBRARY
%token KWMODULE
%token KWDISPINTERFACE
%token KWCOCLASS
%token KWMETHODS
%token KWPROPERTIES
%token KWIMPORTLIB
%token KWFUNCDESCATTR
%token KWIDLDESCATTR
%token KWTYPEDESCATTR
%token KWVARDESCATTR
%token KWSAFEARRAY
%token KWAGGREGATABLE
%token KWUIDEFAULT
%token KWNONBROWSABLE
%token KWDEFAULTCOLLELEM
%token KWDEFAULTVALUE
%token KWCUSTOM
%token KWDEFAULTVTABLE
%token KWIMMEDIATEBIND
%token KWUSESGETLASTERROR
%token KWREPLACEABLE
/* end of ODL key words */
%token KWHANDLET /* Formerly RPCHNDL */
%token KWHANDLE /* Formerly GEN_HNDL */
%token KWCONTEXTHANDLE /* Aka LRPC_CTXT_HNDL */
%token KWMSUNION
%token KWENDPOINT
%token KWDEFAULTPOINTER
%token KWLOCAL
%token KWSWITCHTYPE
%token KWSWITCHIS
%token KWTRANSMITAS
%token KWWIREMARSHAL
%token KWIGNORE
%token KWREF
%token KWUNIQUE
%token KWPTR
%token KWV1ARRAY
%token KWV1STRUCT
%token KWV1ENUM
%token KWV1STRING
%token KWIDEMPOTENT
%token KWBROADCAST
%token KWMAYBE
%token KWASYNC
%token KWINPUTSYNC
%token KWCALLBACK
%token KWALIGN
%token KWUNALIGNED
%token KWOPTIMIZE
%token STRING
%token WIDECHARACTERSTRING
%token KWTOKENNULL
%token NUMERICCONSTANT
%token NUMERICUCONSTANT
%token NUMERICLONGCONSTANT
%token NUMERICULONGCONSTANT
%token HEXCONSTANT
%token HEXUCONSTANT
%token HEXLONGCONSTANT
%token HEXULONGCONSTANT
%token OCTALCONSTANT
%token OCTALUCONSTANT
%token OCTALLONGCONSTANT
%token OCTALULONGCONSTANT
%token CHARACTERCONSTANT
%token WIDECHARACTERCONSTANT
%token IDENTIFIER
%token KWSIZEOF
%token TOKENTRUE
%token TOKENFALSE
/* These are Microsoft C abominations */
%token MSCDECLSPEC
%token MSCDLLIMPORT
%token MSCDLLEXPORT
%token MSCEXPORT
%token MSCFORTRAN
%token MSCCDECL
%token MSCSTDCALL
%token MSCLOADDS
%token MSCSAVEREGS
%token MSCFASTCALL
%token MSCSEGMENT
%token MSCINTERRUPT
%token MSCSELF
%token MSCNEAR
%token MSCFAR
%token MSCUNALIGNED
%token MSCHUGE
%token MSCPASCAL
%token MSCEMIT
%token MSCASM
/* Microsoft proposed extentions to NIDL */
%token KWNOCODE /* Allowed in .IDL in addition to .ACF */
/* These are residual C tokens I'm not sure we should even allow */
%token POINTSTO
%token INCOP
%token DECOP
%token MULASSIGN
%token DIVASSIGN
%token MODASSIGN
%token ADDASSIGN
%token SUBASSIGN
%token LEFTASSIGN
%token RIGHTASSIGN
%token ANDASSIGN
%token XORASSIGN
%token ORASSIGN
%token DOTDOT
%token LTEQ
%token GTEQ
%token NOTEQ
%token LSHIFT
%token RSHIFT
%token ANDAND
%token EQUALS
%token OROR
/* used by lex internally to signify "get another token" */
%token NOTOKEN
/* garbage token - should cause parse errors */
%token GARBAGETOKEN
/* OLE extensions */
%token KWOBJECT
/* Note that we're assuming that we get constants back and can check
bounds (e.g. "are we integer") in the semantic actoins.
*/
/*
ACF - Specific Tokens
*/
%token KWSHAPE
%token KWBYTECOUNT
%token KWIMPLICITHANDLE
%token KWAUTOHANDLE
%token KWEXPLICITHANDLE
%token KWREPRESENTAS
%token KWCALLAS
%token KWCODE
%token KWINLINE
%token KWOUTOFLINE
%token KWINTERPRET
%token KWNOINTERPRET
%token KWCOMMSTATUS
%token KWFAULTSTATUS
%token KWHEAP
%token KWINCLUDE
%token KWPOINTERSIZE
%token KWOFFLINE
%token KWALLOCATE
%token KWENABLEALLOCATE
%token KWMANUAL
%token KWNOTIFY
%token KWNOTIFYFLAG
%token KWUSERMARSHAL
%token KWENCODE
%token KWDECODE
/* Currently Unsupported Tokens */
%token KWBITSET
%token UUIDTOKEN
%token VERSIONTOKEN
%token EOI
%token LASTTOKEN
/* moved to ACF... */
/*****************************************************************************
* %types of various non terminals and terminals
*****************************************************************************/
%type <yy_attr> AcfCallType
%type <yy_graph> AcfImpHdlTypeSpec
%type <yy_attr> AcfInterfaceAttribute
%type <yy_expr> AdditiveExpr
%type <yy_operator> AddOp
%type <yy_expr> AndExpr
%type <yy_expr> ArgExprList
%type <yy_abounds> ArrayBoundsPair
%type <yy_declarator> ArrayDecl
%type <yy_abounds> ArrayDecl2
%type <yy_expr> AssignmentExpr
%type <yy_attrlist> Attributes
%type <yy_attrlist> AttributesWithDefault
%type <yy_attrlist> AttrList
%type <yy_attrlist> AttrListWithDefault
%type <yy_attrlist> AttrSet
%type <yy_attrlist> AttrSetWithDefault
%type <yy_expr> AttrVar
%type <yy_exprlist> AttrVarList
%type <yy_tnlist> BaseInterfaceList
%type <yy_type> BaseTypeSpec
%type <yy_graph> BitSetType
%type <yy_expr> CastExpr
%type <yy_numeric> CHARACTERCONSTANT
%type <yy_type> CharSpecs
%type <yy_siblist> CoclassMember
%type <yy_siblist> CoclassMemberList
%type <yy_string> CoclassName
%type <yy_graph> ComClassDecl
%type <yy_tnlist> ComClassList
%type <yy_graph> ComServer
%type <yy_expr> ConditionalExpr
%type <yy_expr> ConstantExpr
%type <yy_exprlist> ConstantExprs
%type <yy_graph> CPragmaSet
%type <yy_siblist> Declaration
%type <yy_modifiers> DeclarationAccessories
%type <yy_declspec> DeclarationSpecifiers
%type <yy_declarator> Declarator
%type <yy_declarator> Declarator2
%type <yy_siblist> DispatchInterfaceBody
%type <yy_disphead> DispatchInterfaceHeader
%type <yy_string> DispatchInterfaceName
%type <yy_declarator> TypedefDeclarator
%type <yy_declarator_set> TypedefDeclaratorList
%type <yy_declarator_set> TypedefDeclaratorListElement
%type <yy_siblist> DefaultCase
%type <yy_attr> DirectionalAttribute
%type <yy_string> EndPtSpec
%type <yy_attr> EndPtSpecs
%type <yy_declspec> EnumerationType
%type <yy_enlab> Enumerator
%type <yy_enlist> EnumeratorList
%type <yy_declspec> EnumSpecifier
%type <yy_expr> EqualityExpr
%type <yy_expr> ExclusiveOrExpr
%type <yy_expr> Expr
%type <yy_attrlist> FieldAttribute
%type <yy_modifiers> FuncModifier
%type <yy_attr> Guid
%type <yy_numeric> HEXCONSTANT
%type <yy_numeric> HEXLONGCONSTANT
%type <yy_numeric> HEXUCONSTANT
%type <yy_numeric> HEXULONGCONSTANT
%type <yy_pSymName> IDENTIFIER
%type <yy_siblist> Import
%type <yy_siblist> ImportName
%type <yy_siblist> ImportList
%type <yy_expr> InclusiveOrExpr
%type <yy_declarator> InitDeclarator
%type <yy_declarator_set> InitDeclaratorList
%type <yy_short> InternationalCharacterType
%type <yy_type> IntModifiers
%type <yy_short> IntSize
%type <yy_type> IntSpec
%type <yy_expr> Initializer
%type <yy_initlist> InitializerList
%type <yy_siblist> InputFile
%type <yy_attr> InterfaceAttribute
%type <yy_intbody> InterfaceBody
%type <yy_siblist> InterfaceComp
%type <yy_siblist> InterfaceComponent
%type <yy_siblist> InterfaceComponents
%type <yy_inthead> InterfaceHeader
%type <yy_intbody> InterfaceList
%type <yy_string> InterfaceName
%type <yy_string> KWCPRAGMA
%type <yy_intbody> LibraryBody
%type <yy_libhead> LibraryHeader
%type <yy_intbody> LibraryInterfaceList
%type <yy_string> LibraryName
%type <yy_expr> LogicalAndExpr
%type <yy_expr> LogicalOrExpr
%type <yy_siblist> MemberDeclaration
%type <yy_declarator> MemberDeclarator
%type <yy_declarator_set> MemberDeclaratorList
%type <yy_siblist> MethodDeclaration
%type <yy_siblist> MethodList
%type <yy_graph> MidlPragmaSet
%type <yy_modifiers> Modifier
%type <yy_modifiers> ModifierList
%type <yy_siblist> ModuleBody
%type <yy_modulehead> ModuleHeader
%type <yy_string> ModuleName
%type <yy_operator> MultOp
%type <yy_siblist> MultipleImport
%type <yy_expr> MultExpr
%type <yy_siblist> NidlMemberDeclaration
%type <yy_siblist> NidlUnionBody
%type <yy_nucases> NidlUnionCase
%type <yy_nucaselabel> NidlUnionCaseLabel
%type <yy_nucllist> NidlUnionCaseLabelList
%type <yy_nucases> NidlUnionCases
%type <yy_en_switch> NidlUnionSwitch
%type <yy_numeric> NUMERICCONSTANT
%type <yy_numeric> NUMERICLONGCONSTANT
%type <yy_numeric> NUMERICUCONSTANT
%type <yy_numeric> NUMERICULONGCONSTANT
%type <yy_string> ObjectName
%type <yy_numeric> OCTALCONSTANT
%type <yy_numeric> OCTALUCONSTANT
%type <yy_numeric> OCTALLONGCONSTANT
%type <yy_numeric> OCTALULONGCONSTANT
%type <yy_attr> OdlAttribute
%type <yy_attrlist> OneAttribute
%type <yy_attrlist> OneAttributeWithDefault
%type <yy_intbody> OneInterface
%type <yy_attr> OperationAttribute
%type <yy_attrlist> OptionalAttrList
%type <yy_attrlist> OptionalAttrListWithDefault
%type <yy_graph> OptionalBaseIF
%type <yy_short> OptionalComma
%type <yy_modifiers> OptionalConst
%type <yy_declarator> OptionalDeclarator
%type <yy_declarator_set> OptionalInitDeclaratorList
%type <yy_siblist> OptionalMethodList
%type <yy_modifiers> OptionalModifierList
%type <yy_siblist> OptionalModuleBody
%type <yy_siblist> OptionalPropertyList
%type <yy_string> OptionalTag
%type <yy_short> OptPackIndex
%type <yy_attrenum> OptShape
%type <yy_short> PackIndex
%type <yy_graph> ParameterDeclaration
%type <yy_siblist> ParameterList
%type <yy_siblist> ParameterTypeList
%type <yy_siblist> ParamsDecl2
%type <yy_siblist> PhantomInputFile
%type <yy_declarator> Pointer
%type <yy_expr> PostfixExpr
%type <yy_graph> PredefinedTypeSpec
%type <yy_expr> PrimaryExpr
%type <yy_siblist> PropertyList
%type <yy_attr> PtrAttr
%type <yy_modifiers> PtrModifier
%type <yy_short> PushOrPop
%type <yy_expr> RelationalExpr
%type <yy_short> ServerType
%type <yy_expr> ShiftExpr
%type <yy_type> SignSpecs
%type <yy_graph> SimpleTypeSpec
%type <yy_modifiers> StorageClassSpecifier
%type <yy_string> STRING
%type <yy_siblist> StructDeclarationList
%type <yy_en_switch> SwitchSpec
%type <yy_graph> SwitchTypeSpec
%type <yy_string> Tag
%type <yy_declspec> TaggedSpec
%type <yy_declspec> TaggedStructSpec
%type <yy_declspec> TaggedUnionSpec
%type <yy_attr> TypeAttribute
%type <yy_declspec> TypeDeclarationSpecifiers
%type <yy_graph> TYPENAME
%type <yy_graph> TypeName
%type <yy_pSymName> LIBNAME
%type <yy_modifiers> TypeQualifier
%type <yy_declspec> TypeSpecifier
%type <yy_expr> UnaryExpr
%type <yy_expr> UnaryOp
%type <yy_attr> UnimplementedTypeAttribute
%type <yy_siblist> UnionBody
%type <yy_siblist> UnionCase
%type <yy_attr> UnionCaseLabel
%type <yy_siblist> UnionCases
%type <yy_pSymName> UnionName
%type <yy_string> UUIDTOKEN
%type <yy_expr> VariableExpr
%type <yy_string> VERSIONTOKEN
%type <yy_numeric> WIDECHARACTERCONSTANT
%type <yy_string> WIDECHARACTERSTRING
/****************************************************************************/
%%
RpcProg:
ForceBaseIdl InputFile
{
node_source * pSource = new node_source;
pSource->SetMembers( $2 );
pSourceNode = pSource;
/**
** If there were errors detected in the 1st pass, the dont do
** anything.
**/
if( !pCompiler->GetErrorCount() )
{
/**
** If we found no errors, the first compiler phase is over
**/
return;
}
else
{
// if the errors prevented a resolution pass and semantics
// to be performed, then issue a message. For that purpose
// look at the node state of the source node. If it indicates
// presence of a forward decl, then we must issue the error
ParseError( ERRORS_PASS1_NO_PASS2, (char *)0 );
}
/**
** If we reached here, there were errors detected, and we dont
** want to invoke the subsequent passes, Just quit.
**/
pSourceNode = (node_source *)NULL;
returnflag = 1;
return;
}
;
InputFile:
InterfaceList EOI
{
// create file node, add imports
node_file * pFile;
named_node * pN;
char * pInputFileName;
/**
** pick up the details of the file, because we need to set the
** file nodes name with this file
**/
pImportCntrl->GetInputDetails( &pInputFileName );
pFile = new node_file( pInputFileName, ImportLevel );
/**
** Attach the interface nodes as a member of the file node.
** Also, point the interface nodes to their parent file node.
**/
pFile->SetMembers( $1.Members );
MEM_ITER MemIter(pFile);
while ( pN = MemIter.GetNext() )
{
pN->SetFileNode( pFile );
}
/**
** we may have collected the more file nodes as part of the reduction
** process. If so, then attach this node to the list. If not then
** generate a new list and attach the file node there
**/
if( $1.Imports )
$$ = $1.Imports;
else
$$.Init();
$$.SetPeer( pFile );
}
;
InterfaceList:
InterfaceList OneInterface
{
if( !pCommand->IsSwitchDefined( SWITCH_MS_EXT ) )
{
ParseError( MULTIPLE_INTF_NON_OSF, NULL );
}
// if we have dangling definitions, add them to the intf
if ( $2.Members.Tail() &&
( !$2.Members.Tail()->IsInterfaceOrObject() ) )
{
node_interface * pIntf =
pInterfaceInfoDict->GetInterfaceNode();
$$ = $1;
$$.Imports.Merge( $2.Imports );
pIntf->MergeMembersToTail( $2.Members );
if ( $1.Members.Tail() != pIntf )
$$.Members.Add( pIntf );
}
else
{
// merge interface list and imports list
$$ = $1;
$$.Imports.Merge( $2.Imports );
$$.Members.Merge( $2.Members );
}
}
| OneInterface
{
if ( $1.Members.Tail() &&
( !$1.Members.Tail()->IsInterfaceOrObject() ) )
{
node_interface * pIntf =
pInterfaceInfoDict->GetInterfaceNode();
// gets siblist of declarations
pIntf->MergeMembersToTail( $1.Members );
$$.Imports = $1.Imports;
$$.Members.Init( pIntf );
}
else
{
// pass interface list and imports list
$$ = $1;
}
}
;
LibraryInterfaceList:
LibraryInterfaceList OneInterface
{
// merge interface list and imports list
$$ = $1;
$$.Imports.Merge( $2.Imports );
$$.Members.Merge( $2.Members );
}
| OneInterface
;
OneInterface:
InterfaceHeader InterfaceBody '}' OptionalSemicolon
{
/**
** This is the place where the complete interface construct
** has been reduced. We need to hook the body to the interface
** and pass it up, with the imports
**/
node_interface * pInterface = $1.pInterface;
pInterface->SetMembers( $2.Members );
$$.Imports = $2.Imports;
$$.Members.Init( pInterface );
/**
** Start a new interface info dict in case there are
** multiple interfaces in this file.
**/
pInterfaceInfoDict->EndNewInterface();
pInterfaceInfoDict->StartNewInterface();
// start a dummy interface for intervening stuff
node_interface * pOuter = new node_interface;
pOuter->SetSymName( GenIntfName() );
pInterfaceInfoDict->SetInterfaceNode( pOuter );
pOuter->SetAttribute( new battr( ATTR_LOCAL ) );
pOuter->SetProcTbl( (ImportLevel != 0) ? new SymTable : pBaseSymTbl );
}
| OptionalAttrList InterfaceName ';'
{
// put in a forward declaration
SymKey SKey( $2, NAME_DEF );
named_node * pNode;
pNode = new node_forward( SKey, pBaseSymTbl );
pNode->SetSymName( $2 );
// tbd - error if $1.NonNull()
named_node * pFound;
pFound = pBaseSymTbl->SymSearch( SKey );
if (pFound && pFound->NodeKind() != NODE_HREF && pFound->NodeKind() != NODE_INTERFACE && NULL != pFound->GetDefiningFile())
{
pBaseSymTbl->SymDelete( SKey );
}
if(!pBaseSymTbl->SymInsert( SKey, (SymTable *)NULL, pNode ))
{
// ParseError( DUPLICATE_DEFINITION, pName );
}
$$.Imports.Init();
$$.Members.Init( pNode );
}
| OptionalAttrList DispatchInterfaceName ';'
{
// put in a forward declaration
SymKey SKey( $2, NAME_DEF );
named_node * pNode;
pNode = new node_forward( SKey, pBaseSymTbl );
pNode->SetSymName( $2 );
// tbd - error if $1.NonNull()
named_node * pFound;
pFound = pBaseSymTbl->SymSearch( SKey );
if (pFound && pFound->NodeKind() != NODE_HREF && pFound->NodeKind() != NODE_DISPINTERFACE && NULL != pFound->GetDefiningFile())
{
pBaseSymTbl->SymDelete( SKey );
}
if(!pBaseSymTbl->SymInsert( SKey, (SymTable *)NULL, pNode ))
{
// ParseError( DUPLICATE_DEFINITION, pName );
}
$$.Imports.Init();
$$.Members.Init( pNode );
}
| OptionalAttrList CoclassName ';'
{
// put in a forward declaration
SymKey SKey( $2, NAME_DEF );
named_node * pNode;
pNode = new node_forward( SKey, pBaseSymTbl );
pNode->SetSymName( $2 );
// tbd - error if $1.NonNull()
named_node * pFound;
pFound = pBaseSymTbl->SymSearch( SKey );
if (pFound && pFound->NodeKind() != NODE_HREF && pFound->NodeKind() != NODE_COCLASS && NULL != pFound->GetDefiningFile())
{
pBaseSymTbl->SymDelete( SKey );
}
if(!pBaseSymTbl->SymInsert( SKey, (SymTable *)NULL, pNode ))
{
// ParseError( DUPLICATE_DEFINITION, pName );
}
$$.Imports.Init();
$$.Members.Init( pNode );
}
| OptionalAttrList ModuleName ';'
{
// put in a forward declaration
SymKey SKey( $2, NAME_DEF );
named_node * pNode;
pNode = new node_forward( SKey, pBaseSymTbl );
pNode->SetSymName( $2 );
// tbd - error if $1.NonNull()
named_node * pFound;
pFound = pBaseSymTbl->SymSearch( SKey );
if (pFound && pFound->NodeKind() != NODE_HREF && pFound->NodeKind() != NODE_MODULE && NULL != pFound->GetDefiningFile())
{
pBaseSymTbl->SymDelete( SKey );
}
if(!pBaseSymTbl->SymInsert( SKey, (SymTable *)NULL, pNode ))
{
// ParseError( DUPLICATE_DEFINITION, pName );
}
$$.Imports.Init();
$$.Members.Init( pNode );
}
| OptionalAttrList ObjectName ';'
{
// put in a forward declaration
SymKey SKey( $2, NAME_DEF );
named_node * pNode;
pNode = new node_forward( SKey, pBaseSymTbl );
pNode->SetSymName( $2 );
// tbd - error if $1.NonNull()
if(!pBaseSymTbl->SymInsert( SKey, (SymTable *)NULL, pNode ))
{
// ParseError( DUPLICATE_DEFINITION, pName );
}
$$.Imports.Init();
$$.Members.Init( pNode );
}
| Import
{
if( !pCommand->IsSwitchDefined( SWITCH_MS_EXT ) &&
!((node_file*)$1.Tail())->IsXXXBaseIdl() )
{
ParseError( OUTSIDE_OF_INTERFACE, NULL );
}
// returns siblist
// these need to get saved up so they will be added to
// the header file
$$.Imports = $1;
$$.Members.Init();
}
| InterfaceComponent
{
if( !pCommand->IsSwitchDefined( SWITCH_MS_EXT ) )
{
ParseError( OUTSIDE_OF_INTERFACE, NULL );
}
// pass up a sibling list
$$.Imports.Init();
$$.Members = $1;
}
| ComServer
{
$$.Imports.Init();
$$.Members.Init( $1 );
}
| LibraryHeader ForceBaseOdl LibraryBody '}' OptionalSemicolon
{
/**
** This is the place where the complete library construct
** has been reduced. We need to hook the body to the library
** and pass it up, with the imports
**/
node_library * pLibrary = $1.pLibrary;
pLibrary->SetMembers( $3.Members );
$$.Imports = $3.Imports;
$$.Members.Init( pLibrary );
// Throw the big "case sensitive again" switch here
gfCaseSensitive = TRUE;
// return to the previous Import Level
ImportLevel--;
}
| KWIMPORTLIB '(' STRING ')' ';'
{
if ( !FAddImportLib($3) )
{
ParseError(TYPELIB_NOT_LOADED, $3);
}
$$.Imports.Init();
$$.Members.Init();
}
| ModuleHeader PhantomPushSymtab OptionalModuleBody OptionalSemicolon
{
/**
** discard the inner symbol table contents (unless it had fwds)
**/
pCurSymTbl->DiscardScope();
/**
** restore the symbol table level
**/
pSymTblMgr->PopSymLevel( &pCurSymTbl );
node_module * pModule = $1.pModule;
pModule->SetMembers($3);
$$.Members.Init( pModule );
$$.Imports.Init();
/**
** Start a new interface info dict in case there are
** multiple interfaces in this file.
**/
pInterfaceInfoDict->EndNewInterface();
pInterfaceInfoDict->StartNewInterface();
// start a dummy interface for intervening stuff
node_interface * pOuter = new node_interface;
pOuter->SetSymName( GenIntfName() );
pInterfaceInfoDict->SetInterfaceNode( pOuter );
pOuter->SetAttribute( new battr( ATTR_LOCAL ) );
pOuter->SetProcTbl( (ImportLevel != 0) ? new SymTable : pBaseSymTbl );
}
| DispatchInterfaceHeader PhantomPushSymtab DispatchInterfaceBody '}' OptionalSemicolon
{
/**
** discard the inner symbol table contents (unless it had fwds)
**/
pCurSymTbl->DiscardScope();
/**
** restore the symbol table level
**/
pSymTblMgr->PopSymLevel( &pCurSymTbl );
node_dispinterface * pDispInterface = $1.pDispInterface;
pDispInterface->SetMembers($3);
$$.Members.Init(pDispInterface);
$$.Imports.Init();
/**
** Start a new interface info dict in case there are
** multiple interfaces in this file.
**/
pInterfaceInfoDict->EndNewInterface();
pInterfaceInfoDict->StartNewInterface();
// start a dummy interface for intervening stuff
node_interface * pOuter = new node_interface;
pOuter->SetSymName( GenIntfName() );
pInterfaceInfoDict->SetInterfaceNode( pOuter );
pOuter->SetAttribute( new battr( ATTR_LOCAL ) );
pOuter->SetProcTbl( (ImportLevel != 0) ? new SymTable : pBaseSymTbl );
}
| OptionalAttrList CoclassName '{' PhantomPushSymtab CoclassMemberList '}' OptionalSemicolon
{
/**
** discard the inner symbol table contents (unless it had fwds)
**/
pCurSymTbl->DiscardScope();
/**
** restore the symbol table level
**/
pSymTblMgr->PopSymLevel( &pCurSymTbl );
char * szName = $2;
node_coclass * pCoclass = new node_coclass();
pCoclass->AddAttributes($1);
pCoclass->SetSymName(szName);
pCoclass->SetMembers( $5);
// add coclass node to the global symbol table
SymKey SKey (szName, NAME_DEF);
named_node * pFound;
pFound = pBaseSymTbl->SymSearch( SKey );
//if (pFound && ( pFound->NodeKind() == NODE_FORWARD || pFound->NodeKind() == NODE_HREF ))
if (pFound && ( pFound->NodeKind() == NODE_FORWARD || NULL != pFound->GetDefiningFile() ))
{
pBaseSymTbl->SymDelete( SKey );
}
if (!pBaseSymTbl->SymInsert(SKey, (SymTable *) NULL, pCoclass))
{
ParseError(DUPLICATE_DEFINITION, szName);
}
$$.Members.Init( pCoclass );
$$.Imports.Init();
}
;
ModuleHeader:
OptionalAttrList ModuleName '{'
{
char * szName = $2;
node_module * pModule = new node_module();
pModule->AddAttributes($1);
pModule->SetSymName(szName);
// modules get a private scope for procs
pModule->SetProcTbl(new SymTable);
// start the new module
pInterfaceInfoDict->SetInterfaceNode(pModule);
// add module node to the base symbol table
SymKey SKey (szName, NAME_DEF);
named_node * pFound;
pFound = pBaseSymTbl->SymSearch( SKey );
//if (pFound && ( pFound->NodeKind() == NODE_FORWARD || pFound->NodeKind() == NODE_HREF ))
if (pFound && ( pFound->NodeKind() == NODE_FORWARD || NULL != pFound->GetDefiningFile() ))
{
pBaseSymTbl->SymDelete( SKey );
}
if (!pBaseSymTbl->SymInsert(SKey, (SymTable *) NULL, pModule))
{
ParseError(DUPLICATE_DEFINITION, szName);
}
$$.pModule = pModule;
}
;
DispatchInterfaceHeader:
OptionalAttrList DispatchInterfaceName '{'
{
char * szName = $2;
node_dispinterface * pDispInterface = new node_dispinterface();
pDispInterface->AddAttributes($1);
pDispInterface->SetSymName(szName);
// dipatchinterfaces get a private scope for procs
pDispInterface->SetProcTbl(new SymTable);
// start the new dispatchinterface
pInterfaceInfoDict->SetInterfaceNode(pDispInterface);
// add dispinterface node to the global symbol table
SymKey SKey (szName, NAME_DEF);
named_node * pFound;
pFound = pBaseSymTbl->SymSearch( SKey );
//if (pFound && ( pFound->NodeKind() == NODE_FORWARD || pFound->NodeKind() == NODE_HREF ))
if (pFound && ( pFound->NodeKind() == NODE_FORWARD || NULL != pFound->GetDefiningFile() ))
{
pBaseSymTbl->SymDelete( SKey );
}
if (!pBaseSymTbl->SymInsert(SKey, (SymTable *) NULL, pDispInterface))
{
ParseError(DUPLICATE_DEFINITION, szName);
}
$$.pDispInterface = pDispInterface;
}
;
OptionalSemicolon:
';'
| /* nothing */
;
LibraryHeader:
OptionalAttrList LibraryName '{'
{
// make sure that only one library statement exists
char * szName = $2;
if (fLibrary)
{
ParseError(TWO_LIBRARIES, szName);
}
fLibrary = TRUE;
// create library node
node_library * pLibrary = new node_library();
$$.pLibrary = pLibrary;
pLibrary->AddAttributes($1);
pLibrary->SetSymName(szName);
// throw the big "case insensitive" switch here
gfCaseSensitive = FALSE;
// Bump the Import Level to ensure that interfaces under the
// library statement are treated correctly.
ImportLevel++;
}
;
LibraryName:
KWLIBRARY Tag
{
$$ = $2;
}
;
LibraryBody:
LibraryInterfaceList
// just pass back what we get from the list of interfaces
| /* nothing */
{
// initialize and return an empty list
$$.Imports.Init();
$$.Members.Init();
}
;
ModuleName:
KWMODULE Tag
{
$$ = $2;
}
;
OptionalModuleBody:
ModuleBody '}'
| '}'
{
$$.Init();
}
;
ModuleBody:
ModuleBody MethodDeclaration
{
$$.Merge($2);
}
| MethodDeclaration
;
DispatchInterfaceName:
KWDISPINTERFACE Tag
{
$$ = $2;
}
;
DispatchInterfaceBody:
KWPROPERTIES ':' OptionalPropertyList KWMETHODS ':' OptionalMethodList
{
$$ = $3;
$$.Merge($6);
// Can I tell where the properties stop and the methods begin?
// And does it really matter?
}
| InterfaceName ';'
{
// put in a forward declaration
SymKey SKey( $1, NAME_DEF );
named_node * pNode;
pNode = new node_forward( SKey, pBaseSymTbl );
pNode->SetSymName( $1 );
// tbd - error if $1.NonNull()
if(!pBaseSymTbl->SymInsert( SKey, (SymTable *)NULL, pNode ))
{
// ParseError( DUPLICATE_DEFINITION, pName );
}
$$.Init( pNode );
}
| /* nothing */
{
$$.Init();
}
;
OptionalPropertyList:
PropertyList
| /* nothing */
{
$$.Init();
}
;
PropertyList:
PropertyList MemberDeclaration
{
$$.Merge($2);
}
| MemberDeclaration
;
OptionalMethodList:
MethodList
| /* nothing */
{
$$.Init();
}
;
MethodList:
MethodList MethodDeclaration
{
$$.Merge($2);
}
| MethodDeclaration
;
MethodDeclaration:
OptionalAttrList Declaration
{
$2.AddAttributes($1);
$$ = $2;
/**
** Check to see if it has a property attribute.
** If it does, remove its name from the symbol table,
** decorate it with the appropriate decoration
** and re-insert it into the symbol table
**/
BOOL fPropPut = FALSE;
BOOL fPropGet = FALSE;
BOOL fPropPutRef = FALSE;
node_base_attr * pCur = $1.GetFirst();
named_node * pNode = $$.Tail();
char * szName = pNode->GetSymName();
while (pCur)
{
if (pCur->GetAttrID() == ATTR_MEMBER)
{
switch(((node_member_attr *)pCur)->GetAttr())
{
case MATTR_PROPPUT:
fPropPut = TRUE;
if (fPropGet | fPropPutRef)
ParseError(MULTIPLE_PROPERTY_ATTRIBUTES, szName);
break;
case MATTR_PROPGET:
fPropGet = TRUE;
if (fPropPut | fPropPutRef)
ParseError(MULTIPLE_PROPERTY_ATTRIBUTES, szName);
break;
case MATTR_PROPPUTREF:
fPropPutRef = TRUE;
if (fPropGet | fPropPut)
ParseError(MULTIPLE_PROPERTY_ATTRIBUTES, szName);
break;
}
}
pCur = pCur->GetNext();
}
if (fPropPut | fPropGet | fPropPutRef)
{
// remove the name from the correct symbol table
SymKey SKey(szName, NAME_PROC);
SymTable * pSymTable = pInterfaceInfoDict->GetInterfaceProcTable();
named_node * pFound = pSymTable->SymSearch(SKey);
if (pNode == pFound)
{
pSymTable->SymDelete(SKey);
char * szNewName;
if (fPropPut)
{
szNewName = new char[strlen(szName) + 5];
sprintf(szNewName , "put_%s", szName);
}
else
if (fPropGet)
{
szNewName = new char[strlen(szName) + 5];
sprintf(szNewName , "get_%s", szName);
}
else
{
szNewName = new char[strlen(szName) + 8];
sprintf(szNewName , "putref_%s", szName);
}
pFound->SetSymName(szNewName);
SymKey SNewKey(szNewName, NAME_PROC);
pSymTable->SymInsert(SNewKey, (SymTable *)NULL, pFound);
}
else
ParseError(ILLEGAL_USE_OF_PROPERTY_ATTRIBUTE, szName);
}
}
;
CoclassName:
KWCOCLASS Tag
{
$$ = $2;
}
;
CoclassMemberList:
CoclassMemberList CoclassMember
{
$$.Merge($2);
}
| CoclassMember
;
CoclassMember:
OptionalAttrListWithDefault DispatchInterfaceName ';'
{
// put in a forward declaration
SymKey SKey( $2, NAME_DEF );
named_node * pNode;
pNode = new node_forward( SKey, pBaseSymTbl );
pNode->SetSymName( $2 );
// tbd - error if $2.NonNull()
if(!pCurSymTbl->SymInsert( SKey, (SymTable *)NULL, pNode ))
{
// ParseError( DUPLICATE_DEFINITION, pName );
}
// bugbug - how to I verify that the name actually belongs to a DispInterface?
$$.Init( pNode );
$$.AddAttributes($1);
}
| OptionalAttrListWithDefault InterfaceName ';'
{
// put in a forward declaration
SymKey SKey( $2, NAME_DEF );
named_node * pNode;
pNode = new node_forward( SKey, pBaseSymTbl );
pNode->SetSymName( $2 );
// tbd - error if $2.NonNull()
if(!pCurSymTbl->SymInsert( SKey, (SymTable *)NULL, pNode ))
{
// ParseError( DUPLICATE_DEFINITION, pName );
}
// bugbug - how to I verify that the name actually belongs to an Interface?
$$.Init( pNode );
$$.AddAttributes($1);
}
;
ForceBaseOdl:
/* nothing */
{
/* force the lexer to return import "oaidl.idl";
*/
if ( !fOdlBaseImported)
{
/* Make sure the MS_EXT and C_EXT switches get defined
*/
pCommand->SwitchDefined( SWITCH_MS_EXT );
pCommand->SwitchDefined( SWITCH_C_EXT );
// make sure the change sticks
pCommand->SetModeSwitchConfigMask();
LexContext = LEX_ODL_BASE_IMPORT;
fOdlBaseImported = TRUE;
}
}
ForceBaseIdl:
/* nothing */
{
/* force the lexer to return import "idlbase.idl" ;
* in the first interface
*/
if ( !fBaseImported )
{
if( pCommand->IsSwitchDefined( SWITCH_IDLBASE ) )
LexContext = LEX_BASE_IMPORT2;
fBaseImported = TRUE;
}
node_interface * pOuter = new node_interface;
pOuter->SetSymName( GenIntfName() );
pInterfaceInfoDict->SetInterfaceNode( pOuter );
pOuter->SetAttribute( new battr( ATTR_LOCAL ) );
pOuter->SetProcTbl( (ImportLevel != 0) ? new SymTable : pBaseSymTbl );
}
;
InterfaceHeader:
OptionalAttrList InterfaceName OptionalBaseIF '{'
{
node_interface_reference * pRef;
char * pName = $2;
node_interface * pIntf = new node_interface();
$$.pInterface = pIntf;
pIntf->AddAttributes( $1 );
// interfaces with inheritance implicitly become object interfaces now...
if ( $3 )
{
if ( !pIntf->FInSummary( ATTR_OBJECT ) )
{
pIntf->SetAttribute( ATTR_OBJECT );
}
}
// object intfs get a private scope for procs, imported intfs, too
if ( pIntf->FInSummary( ATTR_OBJECT ) ||
( ImportLevel != 0 ) )
pIntf->SetProcTbl( new SymTable );
else
pIntf->SetProcTbl( pBaseSymTbl );
pIntf->SetSymName( pName );
if ( !strcmp( pName, "IUnknown" ) )
pIntf->SetValidRootInterface();
pRef = new node_interface_reference( pIntf );
// add the interface reference node to the base symbol table as if
// it were a typedef
SymKey SKey( pName, NAME_DEF );
named_node * pFound;
pFound = pBaseSymTbl->SymSearch( SKey );
//if ( pFound && ( pFound->NodeKind() == NODE_FORWARD || pFound->NodeKind() == NODE_HREF) )
if (pFound && ( pFound->NodeKind() == NODE_FORWARD || NULL != pFound->GetDefiningFile() ))
{
pBaseSymTbl->SymDelete( SKey );
}
if(!pBaseSymTbl->SymInsert( SKey, (SymTable *)NULL, pRef ))
{
ParseError( DUPLICATE_DEFINITION, pName );
}
// set the base interface of this interface
// this MAY be a node_forward
pIntf->SetMyBaseInterfaceReference( (named_node *) $3 );
// start the new interface
pInterfaceInfoDict->SetInterfaceNode( pIntf );
}
| OptionalAttrList ObjectName BaseInterfaceList '{'
{
node_interface_reference * pRef;
char * pName = $2;
node_object * pIntf = new node_object();
$$.pInterface = pIntf;
pIntf->AddAttributes( $1 );
// objects get a private scope for procs
pIntf->SetProcTbl( new SymTable );
pIntf->SetSymName( pName );
pRef = new node_interface_reference( pIntf );
// add the interface reference node to the base symbol table as if
// it were a typedef
SymKey SKey( pName, NAME_DEF );
named_node * pFound;
pFound = pBaseSymTbl->SymSearch( SKey );
//if ( pFound && ( pFound->NodeKind() == NODE_FORWARD || pFound->NodeKind() == NODE_HREF ))
if (pFound && ( pFound->NodeKind() == NODE_FORWARD || NULL != pFound->GetDefiningFile() ))
{
pBaseSymTbl->SymDelete( SKey );
}
if(!pBaseSymTbl->SymInsert( SKey, (SymTable *)NULL, pRef ))
{
ParseError( DUPLICATE_DEFINITION, pName );
}
// set the base interface list of this object
// this MAY include node_forwards
pIntf->SetMyBaseInterfaceList( $3 );
// start the new interface/object
pInterfaceInfoDict->SetInterfaceNode( pIntf );
}
;
OptionalBaseIF:
':' Tag
{
node_skl * pNode;
SymKey SKey( $2, NAME_DEF );
BOOL fNotFound =
! ( pNode = pBaseSymTbl->SymSearch( SKey ) );
if( fNotFound || (pNode->NodeKind() == NODE_FORWARD ) )
{
pNode = new node_forward( SKey, pBaseSymTbl );
((named_node *)pNode)->SetSymName( $2 );
}
//Return a node_forward or a node_interface_reference.
$$ = pNode;
}
| /* Empty */
{
$$ = NULL;
}
;
BaseInterfaceList:
':' Tag
{
node_skl * pNode;
SymKey SKey( $2, NAME_DEF );
BOOL fNotFound =
! ( pNode = pBaseSymTbl->SymSearch( SKey ) );
if( fNotFound || (pNode->NodeKind() == NODE_FORWARD ) )
{
pNode = new node_forward( SKey, pBaseSymTbl );
((named_node *)pNode)->SetSymName( $2 );
}
//Return a new list with a node_forward or a node_interface_reference.
$$ = new type_node_list;
if( pNode )
$$->SetPeer( pNode );
}
| BaseInterfaceList ',' Tag
{
node_skl * pNode;
SymKey SKey( $3, NAME_DEF );
BOOL fNotFound =
! ( pNode = pBaseSymTbl->SymSearch( SKey ) );
if( fNotFound || (pNode->NodeKind() == NODE_FORWARD ) )
{
pNode = new node_forward( SKey, pBaseSymTbl );
((named_node *)pNode)->SetSymName( $3 );
}
//Add a node_forward or a node_interface_reference to the list.
$$ = $1;
$$->SetPeer(pNode);
}
;
InterfaceName:
KWINTERFACE Tag
{
$$ = $2;
}
;
ObjectName:
KWCLASS Tag
{
// complain if they werent supposed to use these
if ( !pCommand->IsComClassOK() )
ParseError( UNDEFINED_SYMBOL, "class" );
$$ = $2;
}
;
ComServer:
ServerType OptionalTag '{' ComClassList '}'
{
node_com_server * pServer = new node_com_server( $2 );
pServer->SetServerType( $1 );
pServer->SetClassList( $4 );
$$ = pServer;
}
;
ComClassList:
ComClassList ComClassDecl
{
$$ = $1;
$$->SetPeer( $2 );
}
| ComClassDecl
{
type_node_list * pList = new type_node_list( $1 );
$$ = pList;
}
;
TypeName:
TYPENAME
| LIBNAME "." TYPENAME
{
char * szType = $3->GetSymName();
node_skl * pNode = (named_node *)AddQualifiedReferenceToType($1, szType);
if (!pNode)
{
char * sz = new char [strlen($1) + strlen(szType) + 2];
strcpy(sz, $1);
strcat(sz, ".");
strcat(sz, szType);
ParseError( UNDEFINED_SYMBOL, sz);
pNode = $3;
}
$$ = pNode;
}
;
ComClassDecl:
KWCLASS TypeName ';'
{
$$ = $2;
}
;
ServerType:
KWDLLSERVER
{
// complain if they werent supposed to use these
if ( !pCommand->IsComClassOK() )
ParseError( UNDEFINED_SYMBOL, "dllserver" );
$$ = COM_SERVER_IS_DLL;
}
| KWEXESERVER
{
// complain if they werent supposed to use these
if ( !pCommand->IsComClassOK() )
ParseError( UNDEFINED_SYMBOL, "exeserver" );
$$ = COM_SERVER_IS_EXE;
}
;
InterfaceBody:
MultipleImport InterfaceComp
{
/**
** This production is reduced when there is at least 1 imported
** file
**/
$$.Imports = $1;
$$.Members = $2;
}
| InterfaceComp
{
/**
** This production is reduced when there is NO import in the file
**/
$$.Imports.Init();
$$.Members = $1;
}
;
/**
** All the interface components have been reduced.
**/
InterfaceComp:
InterfaceComponents
| /* Nothing */
{
$$.Init();
}
;
MultipleImport:
MultipleImport Import
{
$$ = $1;
$$.Merge( $2 );
}
| Import
;
Import:
KWIMPORT ImportList ';'
{
$$ = $2;
}
| KWIMPORTIDLBASE ImportList
{
$$ = $2;
((node_file*)$$.Tail()) ->SetXXXBaseIdl();
}
| KWIMPORTODLBASE ImportList
{
$$ = $2;
}
;
ImportList:
ImportName
| ImportList ',' ImportName
{
$$ = $1;
$$.Merge( $3 );
}
;
/**
** Imports are handled by making them part of the syntax. The following set of
** productions control the import. As soon as an import string is seen, we
** must get the productions from another idl file. It would be great if we
** could recursively call the parser here. But yacc does not generate a
** parser which can be recursivel called. So we make the idl syntax right
** recursive by introducing "InputFile" at the rhs of the Importname
** production. The type graph then gets generated with the imported parts of
** the type graph compeleting first. We keep merging the type graphs from the
** imported files. The beauty of this is that the parser does not have to do
** any work at all. The parse tells the import controller to push his import
** level, and switch input from another file. The import controller can do
** this very easily. Then when the parser driver asks for the next token, it
** will be from the imported file. Thus the parser conspires with the file
** handler to fool itself and the lexer. This whole scheme makes it very
** easy on all components - the parser, lexer and the file handler.
**
** import of an already imported file is an idempotent operation. We can
** generate the type graph of the reduncdantly imported file and then throw it
** away, but that is wasteful. Again, the file handler helps. If it finds that
** a file was redundantly imported, it just sets itself up so that it returns
** an end of file on the next getchar operation on the file. This makes it
** very easy for the parser. It can either expect an interface syntax after the
** import statement or it can expect an end of file. Thus 2 simple productions
** take care of this entire problem.
**/
ImportName:
STRING
{
/**
** we just obtained the import file name as a string. Immediately
** following, we must switch the input from the imported file.
**/
// push the current case sensitive setting on the stack
gCaseStack.Push(gfCaseSensitive);
// switch to case sensitive mode
gfCaseSensitive = TRUE;
pImportCntrl->PushLexLevel();
if( pImportCntrl->SetNewInputFile( $1 ) != STATUS_OK )
{
$$.Init();
returnflag = 1;
return;
}
/**
** update the quick reference import level indicator
**/
ImportLevel++;
// the new file gets its own Zp stack
PushZpStack( pPackStack, CurrentZp );
// prepare for anything not in an interface body
pInterfaceInfoDict->StartNewInterface();
node_interface * pOuter = new node_interface;
pOuter->SetSymName( GenIntfName() );
pInterfaceInfoDict->SetInterfaceNode( pOuter );
pOuter->SetAttribute( new battr( ATTR_LOCAL ) );
pOuter->SetProcTbl( (ImportLevel != 0) ? new SymTable : pBaseSymTbl );
}
PhantomInputFile
{
/**
** The phantom interface production is introduced to unify the actions
** from a successful and unsuccessful import. An import can be
** errorneous if the file being imported has been imported before.
**/
BOOL fError = !( ( $$ = $3 ).NonNull() );
/**
** Restore the lexical level of the import controller.
**/
pImportCntrl->PopLexLevel();
pInterfaceInfoDict->EndNewInterface();
// return to the enclosing files Zp stack
PopZpStack( pPackStack, CurrentZp );
ImportLevel--;
//
// The filehandler will return an end of file if the file was a
// redundant import OR there was a genuine end of file. It will set
// a flag, fRedundantImport to differentiate between the two situations.
// Report different syntax errors in both these cases.
//
if( fError )
{
if( fRedundantImport )
ParseError( REDUNDANT_IMPORT, $1 );
else
{
ParseError( UNEXPECTED_END_OF_FILE, $1 );
}
}
fRedundantImport = FALSE;
// pop the previous case sensitive mode back off the stack
gCaseStack.Pop(gfCaseSensitive);
}
;
PhantomInputFile:
InputFile
{
/**
** InputFile is a list of file nodes
**/
char * pInputFileName;
$$ = $1;
pImportCntrl->GetInputDetails( &pInputFileName );
AddFileToDB( pInputFileName );
}
| EOI
{
$$.Init();
}
;
InterfaceComponents:
InterfaceComponents InterfaceComponent
{
$$ = $1;
$$.Merge( $2 );
}
| InterfaceComponent
;
/* Note that we have to semantically verify that the declaration
which has operation attributes is indeed a function prototype. */
InterfaceComponent:
CPragmaSet
{
$$.Init($1);
}
| MidlPragmaSet
{
$$.Init($1);
}
| KWCPPQUOTE '(' STRING ')'
{
ParseError( CPP_QUOTE_NOT_OSF, (char *)0 );
$3 = MakeNewStringWithProperQuoting( $3 );
$$.Init( new node_echo_string( $3 ) );
}
| MethodDeclaration
;
CPragmaSet:
KWCPRAGMA
{
/**
** we need to emit the c pragma strings as they are.
** we introduce the echo string node, so that the back end can
** emit it without even knowing the difference.
**/
#define PRAGMA_PACK_STRING ("#pragma pack( ")
#define PRAGMA_STRING ("#pragma ")
char * p = new char [ strlen( $1 ) + strlen( PRAGMA_STRING ) + 1 ];
strcpy( p, PRAGMA_STRING );
strcat( p, $1 );
$$ = new node_echo_string( p );
}
| KWCPRAGMAPACK '(' ')'
{
node_pragma_pack * pPack;
/* return to global packing level */
pPack = new node_pragma_pack( NULL,
pCommand->GetZeePee(),
PRAGMA_PACK_RESET );
CurrentZp = pCommand->GetZeePee();
$$ = pPack;
}
| KWCPRAGMAPACK '(' PackIndex ')'
{
/* set current packing level */
if ( $3 )
{
node_pragma_pack * pPack;
/* switch top to new packing level */
pPack = new node_pragma_pack( NULL,
0,
PRAGMA_PACK_SET,
$3 );
CurrentZp = $3;
$$ = pPack;
}
else
$$ = NULL;
}
| KWCPRAGMAPACK '(' PushOrPop OptPackIndex ')'
{
node_pragma_pack * pPack;
switch( $3 )
{
case PRAGMA_PACK_PUSH:
{
// do push things
// push current zp
/* switch top to new packing level */
pPack = new node_pragma_pack( NULL,
CurrentZp,
PRAGMA_PACK_PUSH,
$4 );
pPack->Push( pPackStack );
$$ = pPack;
if ( $4 )
CurrentZp = $4;
break;
}
case PRAGMA_PACK_POP:
{
// do pop things
/* switch top to new packing level */
pPack = new node_pragma_pack( NULL,
$4,
PRAGMA_PACK_POP );
CurrentZp = pPack->Pop( pPackStack );
if ( !CurrentZp )
{
CurrentZp = pCommand->GetZeePee();
ParseError(MISMATCHED_PRAGMA_POP, NULL );
}
$$ = pPack;
break;
}
default:
$$ = NULL;
}
}
| KWCPRAGMAPACK '(' PushOrPop ',' IDENTIFIER OptPackIndex ')'
{
node_pragma_pack * pPack;
switch( $3 )
{
case PRAGMA_PACK_PUSH:
{
// do push things
// push current zp
/* switch top to new packing level */
pPack = new node_pragma_pack( $5,
CurrentZp,
PRAGMA_PACK_PUSH,
$6 );
pPack->Push( pPackStack );
$$ = pPack;
if ( $6 )
CurrentZp = $6;
break;
}
case PRAGMA_PACK_POP:
{
// do pop things
/* switch top to new packing level */
pPack = new node_pragma_pack( $5,
$6,
PRAGMA_PACK_POP );
CurrentZp = pPack->Pop( pPackStack );
if ( !CurrentZp )
{
CurrentZp = pCommand->GetZeePee();
ParseError(MISMATCHED_PRAGMA_POP, NULL );
}
$$ = pPack;
break;
}
default:
$$ = NULL;
}
}
;
PushOrPop:
IDENTIFIER
{
if ( !strcmp( $1, "push" ) )
{
$$ = PRAGMA_PACK_PUSH;
}
else if ( !strcmp( $1, "pop" ) )
{
$$ = PRAGMA_PACK_POP;
}
else
{
ParseError( UNKNOWN_PRAGMA_OPTION, $1);
$$ = PRAGMA_PACK_GARBAGE;
}
}
;
OptPackIndex:
',' PackIndex
{
$$ = $2;
}
| /* null */
{
$$ = 0;
}
;
PackIndex:
NUMERICCONSTANT
{
switch ( $1.Val )
{
case 1:
case 2:
case 4:
case 8:
$$ = (short) $1.Val;
break;
default:
ParseError( UNKNOWN_PRAGMA_OPTION, $1.pValStr);
$$ = 0;
}
}
;
MidlPragmaSet:
KWMPRAGMAIMPORT '(' IDENTIFIER ')'
{
/**
** We need to set import on and off here
**/
char * p;
if( strcmp( $3, "off" ) == 0 )
{
p = "/* import off */";
fPragmaImportOn = FALSE;
}
else if( strcmp( $3, "on" ) == 0 )
{
p = "/* import on */";
fPragmaImportOn = TRUE;
}
else
p = "/* import unknown */";
$$ = new node_echo_string( p );
}
| KWMPRAGMAECHO '(' STRING ')'
{
$3 = MakeNewStringWithProperQuoting( $3 );
$$ = new node_echo_string( $3 );
}
| KWMPRAGMAIMPORTCLNTAUX '(' STRING ',' STRING ')'
{
$$ = NULL;
}
| KWMPRAGMAIMPORTSRVRAUX '(' STRING ',' STRING ')'
{
$$ = NULL;
}
;
Declaration:
KWTYPEDEF OptionalAttrList TypeDeclarationSpecifiers TypedefDeclaratorList
{
/**
** create new typedef nodes for each of the declarators, apply any
** type attributes to the declarator. The declarators will have a
** basic type as specied by the Declaration specifiers.
** Check for the presence of a init expression. The typedef derives
** the declarators from the same place as the other declarators, so
** an init list must be explicitly checked for and reported as a
** syntax error. But dont report errors for each declarator, instead
** report it only once at the end.
**/
class _DECLARATOR * pDec;
char * pName;
node_skl * pType;
DECLARATOR_LIST_MGR pDeclList( $4 );
/**
** prepare for a list of typedefs to be made into interface
** components
**/
$$.Init();
while( pDec = pDeclList.DestructiveGetNext() )
{
node_def_fe * pDef = (node_def_fe *) pDec->pHighest;
pType = $3.pNode;
if (NULL == pDef)
{
/**
** The declaration is a forward declaration following the
** goofy mktyplib syntax: typedef struct foo; (or union).
** We need to verify that the mktyplib203 switch is set
** (only allow this syntax in mktyplib compatibility mode)
** and we need to create a forward declaration so that
** future references will resolve correctly.
**/
pName = pType->GetSymName();
SymKey SKey( pName, NAME_DEF );
node_forward * pFwd = new node_forward( SKey, pCurSymTbl );
pFwd->SetSymName( pName );
pDef = new node_def_fe(pName, pFwd);
pDec->Init(pDef);
if (!pCommand->IsSwitchDefined(SWITCH_MKTYPLIB))
ParseError( ILLEGAL_USE_OF_MKTYPLIB_SYNTAX, pName);
}
else
{
pName = pDef->GetSymName();
}
/**
** set the basic type of the declarator.
**/
pDec->pLowest->SetChild( pType );
// complain about invalid redef of wchar_t or error_status_t
if (pName)
{
if ( strcmp( pName, "wchar_t" ) == 0 )
{
node_skl * pN = pType;
if( !((pN->NodeKind() == NODE_SHORT) &&
pN->FInSummary( ATTR_UNSIGNED) ) )
{
ParseError( WCHAR_T_ILLEGAL, (char *)0 );
}
}
else if( strcmp( pName, "error_status_t" ) == 0 )
{
node_skl * pN = pType;
if( !((pN->NodeKind() == NODE_LONG) &&
pN->FInSummary( ATTR_UNSIGNED) ) )
{
ParseError( ERROR_STATUS_T_ILLEGAL, (char *)0 );
}
}
}
else
ParseError( BENIGN_SYNTAX_ERROR, "" );
//
// if the type specifier is a forward declared type, then
// the only syntax allowed is when context_handle is applied
// to the type. If not, report an error
//
//gaj CheckSpecialForwardTypedef( pDef, pType, $2);
/**
** The typedef node graph is all set up,
** apply attributes and enter into symbol table
**/
$$.Add( pDef );
/**
** Remember that we have to apply the attributes to each of
** the declarators, so we must clone the attribute list for
** each declarator, the apply the type attribute list to each
** of the declarators
**/
if ( $2.NonNull() )
{
pDef->AddAttributes( $2 );
}
/**
** similarly, apply the remnant attributes collected from
** declaration specifiers, to the declarator
**
** Only the first declarator to use a composite type gets to
** be the declaration; all the others reference that declaration;
** e.g. struct FOO { xxx } foo, *pfoo
** is treated as: struct FOO { xxx } foo
** struct FOO *pfoo
**/
#ifdef gajdebug11
printf("setting modifiers %08x on %s\n",
$3.modifiers,
(pName)? pName : "(unknown)" );
#endif
pDec->pLowest->SetModifiers( $3.modifiers );
$3.modifiers |= SetModifierBit( ATTR_TAGREF );
}
}
| DeclarationSpecifiers OptionalInitDeclaratorList ';'
{
/**
** All declarations other than typedefs are collected here.
** They are collected and passed up to the interface component
** production
**/
node_skl * pType = $1.pNode;
DECLARATOR_LIST_MGR DeclList( $2 );
long TempModifiers;
long TopModifiers;
#ifdef gajdebug3
printf("DeclarationSpecifiers OptionalInitDeclaratorList\n");
#endif
$$.Init();
/**
** It is possible that there are no declarators, only a type decla-
** ration. eg, the definition of a structure.
**/
if ( DeclList.NonEmpty() )
{
class _DECLARATOR * pDec;
/**
** for each declarator, set the basic type, set the attributes
** if any
**/
while( pDec = DeclList.DestructiveGetNext() )
{
pDec->pLowest->SetChild( pType );
/**
** Apply the remnant attributes from the declaration specifier
** prodn to this declarator;
**/
// magic trick to push extern, etc up to top
TempModifiers = $1.modifiers;
TopModifiers = TempModifiers & 0x0000000f;
TempModifiers -= TopModifiers;
pDec->pLowest->SetModifiers( TempModifiers );
pDec->pHighest->SetModifiers( TopModifiers );
$1.modifiers |= SetModifierBit( ATTR_TAGREF );
/**
** shove the type node up.
**/
$$.Add( (named_node *) pDec->pHighest );
}
}
else
{
#ifdef gajdebug3
printf("\t\t...no declarators\n");
#endif
/**
** This is the case when no specific declarator existed. Just
** pass on the declaration to interface component. However, it
** is possible that the declaration is a forward declaration,
** in that case, just generate a dummy typedef. The dummy typedef
** exists, so that the whole thing is transparent to the back end.
**/
named_node * pDef = (named_node *) $1.pNode;
/**
** Apply the remnant attributes from the declaration specifier
** prodn to this declarator;
**/
if( $1.modifiers )
{
pDef->SetModifiers( $1.modifiers );
}
/**
** shove the type node up.
**/
$$.Add( pDef );
}
}
;
TypeDeclarationSpecifiers:
DeclarationSpecifiers
| IDENTIFIER
{
node_forward * pFwd;
SymKey SKey( $1, NAME_DEF );
pFwd = new node_forward( SKey, pCurSymTbl );
pFwd->SetSymName( $1 );
$$.pNode = pFwd;
$$.modifiers = 0;
}
;
SimpleTypeSpec:
BaseTypeSpec
{
node_base_type * pNode;
GetBaseTypeNode( (node_skl**) &pNode,
$1.TypeSign,
$1.TypeSize,
$1.BaseType);
$$ = pNode;
if ( pNode->NodeKind() == NODE_INT )
ParseError( BAD_CON_INT, NULL );
}
| PredefinedTypeSpec
| TypeName /* TYPENAME */
;
DeclarationSpecifiers:
DeclarationAccessories TypeSpecifier
{
$$.pNode = $2.pNode;
$$.modifiers = $1 | $2.modifiers;
}
| TypeSpecifier
;
DeclarationAccessories:
DeclarationAccessories StorageClassSpecifier
{
$$ = $1 | $2;
}
| DeclarationAccessories TypeQualifier
{
$$ = $1 | $2;
}
| StorageClassSpecifier
| TypeQualifier
;
StorageClassSpecifier:
KWEXTERN
{
$$ = SetModifierBit(ATTR_EXTERN);
}
| KWSTATIC
{
$$ = SetModifierBit(ATTR_STATIC);
}
| KWAUTO
{
$$ = SetModifierBit(ATTR_AUTO);
}
| KWREGISTER
{
$$ = SetModifierBit(ATTR_REGISTER);
}
;
TypeSpecifier:
BaseTypeSpec
{
node_base_type * pNode;
GetBaseTypeNode( (node_skl**) &pNode,
$1.TypeSign,
$1.TypeSize,
$1.BaseType);
$$.pNode = pNode;
if ( pNode->NodeKind() == NODE_INT )
ParseError( BAD_CON_INT, NULL );
$$.modifiers = SetModifierBit(ATTR_TAGREF);
}
| PredefinedTypeSpec
{
$$.pNode = $1;
$$.modifiers = SetModifierBit(ATTR_TAGREF);
}
| TaggedSpec
| EnumerationType
| BitSetType
{
$$.pNode = $1;
$$.modifiers = SetModifierBit(ATTR_TAGREF);
}
| TypeName /* TYPENAME */
{
/**
** Note that there is no need to check for whether the symbol table
** has the entry or not. If it did not, the TYPENAME token would not
** have come in. If the TYPENAME is for a forward reference, see
** if it has been satisfied; if so, create a NEW typedef that is the
** same, but without the forward reference.
**/
node_def_fe * pDef = (node_def_fe *) $1;
if ( ( pDef->NodeKind() == NODE_DEF ) &&
pDef->GetChild() &&
( pDef->GetChild()->NodeKind() == NODE_FORWARD ) )
{
node_forward * pFwd = (node_forward *) pDef->GetChild();
node_skl * pNewSkl = pFwd->ResolveFDecl();
if ( pNewSkl )
{
ATTRLIST alist;
pDef->GetAttributeList(alist);
pDef = new node_def_fe( pDef->GetSymName(), pNewSkl );
pDef->SetAttributes(alist);
SymKey SKey(pDef->GetSymName(), NAME_DEF);
pBaseSymTbl->SymDelete(SKey);
pBaseSymTbl->SymInsert(SKey, (SymTable *) NULL, (named_node*) pDef);
}
};
$$.pNode = pDef;
$$.modifiers = SetModifierBit(ATTR_TAGREF);
}
| KWSAFEARRAY DeclarationSpecifiers OptionalDeclarator ')'
{
node_skl * pNode = pErrorTypeNode;
if( $2.pNode )
{
if( $3.pHighest )
{
$3.pLowest->SetChild( $2.pNode );
pNode = $3.pHighest;
if( $2.modifiers )
{
( (named_node *) $3.pLowest)->SetModifiers( $2.modifiers );
}
}
else
pNode = $2.pNode;
}
$$.pNode = new node_safearray( pNode );
$$.modifiers = SetModifierBit(ATTR_TAGREF);
}
| KWPIPE TypeSpecifier
{
node_skl * pNode = pErrorTypeNode;
if ($2.pNode )
{
pNode = $2.pNode;
}
$$.pNode = new node_pipe( pNode );
$$.modifiers = SetModifierBit(ATTR_TAGREF) ;
}
;
BitSetType:
IntSize KWBITSET '{' IdentifierList '}'
{
ParseError( UNIMPLEMENTED_FEATURE, "bitset" );
$$ = pErrorTypeNode;
}
;
IdentifierList:
IDENTIFIER
| IdentifierList ',' IDENTIFIER
;
EnumerationType:
/**
IntSize EnumSpecifier
**/
EnumSpecifier
;
EnumSpecifier:
KWENUM OptionalTag '{' EnumeratorList OptionalComma '}'
{
/**
** We just obtained a complete enum definition. Check for
** duplicate definition and break circular label list;
**/
BOOL fFound = FALSE;
BOOL fEnumIsForwardDecl = FALSE;
node_skl * pNode;
SymKey SKey( $2, NAME_ENUM );
pNode = pBaseSymTbl->SymSearch( SKey );
if( fFound = (pNode != (node_skl *) NULL) )
fEnumIsForwardDecl = ( pNode->NodeKind() == NODE_FORWARD || pNode->NodeKind() == NODE_HREF );
if( fFound && !fEnumIsForwardDecl )
{
ParseError( DUPLICATE_DEFINITION, $2 );
$$.pNode = (node_skl *)pErrorTypeNode;
}
else
{
/**
** This is a new definition of enum. Enter into symbol table
** Also, pick up the label graph and attach it.
**/
node_enum * pEnum = new node_enum( $2 );
$$.pNode = pEnum;
pEnum->SetMembers( $4.NodeList );
/**
** Note that the enum symbol table entry need not have a next
** scope since the enum labels are global in scope.If the enum was
** a forward decl into the symbol table, delete it.
**/
if( fEnumIsForwardDecl )
{
pBaseSymTbl->SymDelete( SKey );
}
pBaseSymTbl->SymInsert( SKey,
(SymTable *)NULL,
(named_node *) $$.pNode );
CheckGlobalNamesClash( SKey );
}
// if the enumerator is sparse, report an error if the
// switch configuration is not correct.
if( $4.fSparse )
ParseError( SPARSE_ENUM, (char *)NULL );
$$.modifiers = 0;
}
| KWENUM Tag
{
/**
** Search for the enum definition, if not found, return the type
** as a forward declarator node. The semantic analysis will register
** the forward declaration and resolve it when the second pass occurs.
** See TaggedStruct production for a description on why we want to
** enter even a fdecl enum in the symbol table.
**/
SymKey SKey( $2, NAME_ENUM );
BOOL fNotFound = ! ( $$.pNode = pBaseSymTbl->SymSearch( SKey ) );
if( fNotFound || ($$.pNode->NodeKind() == NODE_FORWARD ) )
{
$$.pNode = new node_forward( SKey, pBaseSymTbl );
}
$$.modifiers = SetModifierBit(ATTR_TAGREF);
}
;
EnumeratorList:
Enumerator
{
/**
** this is the first label on an enum list. Set up the circular list
** pointing to the tail, and set it's expr to 0L if there was none
**/
expr_node * pExpr;
node_label * pLabel = (node_label *) $1.pLabel;
pExpr = ($1.pExpr)
? $1.pExpr
: GetConstant0();
pLabel->pExpr = pExpr;
$$.fSparse = $1.fSparse;
$$.pPrevLabel = pLabel;
$$.NodeList.Init( pLabel );
}
| EnumeratorList ',' Enumerator
{
/**
** This is a new label we reduced.
**
** if there was an expression associated with the label, use that
** else use the already collected expression, and add 1 to it.
**/
expr_node * pExpr = (expr_node *)0;
node_label * pLabel = (node_label *) $3.pLabel;
pExpr = $3.pExpr;
// next node has no expression, give it an expression of:
// <prev label> + 1;
if (pExpr == NULL )
{
expr_named_constant * pPrev =
new expr_named_constant( $1.pPrevLabel->GetSymName(),
$1.pPrevLabel );
pExpr = new expr_b_arithmetic(OP_PLUS,
pPrev,
GetConstant1() );
}
pLabel->pExpr = pExpr;
$$ = $1;
$$.NodeList.Add( pLabel );
$$.pPrevLabel = pLabel;
$$.fSparse += $3.fSparse;
}
;
Enumerator:
OptionalAttrList IDENTIFIER
{
/**
** We have obtained an enum label, without an expression. Since
** we dont know if this is the first label (most probably not),
** we just indicate the absence of an expression by an NULL pointer.
** The next parse state would know if this was the first or not
** and take appropriate action
**
** The enum labels go into the global name space. Search for
** duplicates on the base symbol table.
**/
node_label * pLabel;
SymKey SKey( $2, NAME_LABEL );
if( pBaseSymTbl->SymSearch( SKey ) )
{
ParseError( DUPLICATE_DEFINITION, $2 );
pLabel = new node_label( GenTempName(), NULL );
}
else
{
/**
** If the label has an expression, use it, else it is 0. Also
** propogate the expression to $$, so that the next labels will
** get it. Note that we DO NOT evaluate the expressions here.
** The MIDL compiler will evaluate the expressions later.
**/
pLabel = new node_label( $2, NULL );
/**
** Insert into the global table
**/
pBaseSymTbl->SymInsert(SKey, (SymTable *)NULL,(named_node *)pLabel);
CheckGlobalNamesClash( SKey );
}
if ( $1.NonNull() )
{
pLabel->AddAttributes( $1 );
}
$$.pLabel = pLabel;
$$.pExpr = NULL;
$$.fSparse = 0;
}
| OptionalAttrList IDENTIFIER '=' ConstantExpr
{
/**
** This enum label has an expression associated with it. Use it.
** sparse enums are illegal in osf mode
**/
node_label * pLabel;
SymKey SKey( $2, NAME_LABEL );
if ($4->IsStringConstant())
ParseError(ENUM_TYPE_MISMATCH, $2);
if( pBaseSymTbl->SymSearch( SKey ) )
{
ParseError( DUPLICATE_DEFINITION, $2 );
pLabel = new node_label( GenTempName(), NULL );
}
else
{
/**
** If the label has an expression, use it, else it is 0. Also
** propogate the expression to $$, so that the next labels will
** get it. Note that we DO NOT evaluate the expressions. The MIDL
** compiler will just dump the expressions for the c compiler to
** evaluate.
**/
pLabel = new node_label( $2, $4 );
/**
** Insert into the global table
**/
pBaseSymTbl->SymInsert(SKey, (SymTable *)NULL,(named_node *)pLabel);
CheckGlobalNamesClash( SKey );
}
if ( $1.NonNull() )
{
pLabel->AddAttributes( $1 );
}
$$.pLabel = pLabel;
$$.pExpr = $4;
$$.fSparse = 1;
}
;
PredefinedTypeSpec:
InternationalCharacterType
{
ParseError( UNIMPLEMENTED_TYPE, KeywordToString( $1 ) );
$$ = (node_skl *)pErrorTypeNode;
}
;
BaseTypeSpec:
KWFLOAT
{
$$.BaseType = TYPE_FLOAT;
$$.TypeSign = SIGN_UNDEF;
$$.TypeSize = SIZE_UNDEF;
}
| KWLONG KWDOUBLE
{
$$.BaseType = TYPE_DOUBLE;
$$.TypeSign = SIGN_UNDEF;
$$.TypeSize = SIZE_UNDEF;
}
| KWDOUBLE
{
$$.BaseType = TYPE_DOUBLE;
$$.TypeSign = SIGN_UNDEF;
$$.TypeSize = SIZE_UNDEF;
}
| KWVOID
{
$$.BaseType = TYPE_VOID;
$$.TypeSign = SIGN_UNDEF;
$$.TypeSize = SIZE_UNDEF;
}
| KWBOOLEAN
{
$$.BaseType = TYPE_BOOLEAN;
$$.TypeSign = SIGN_UNDEF;
$$.TypeSize = SIZE_UNDEF;
}
| KWBYTE
{
$$.BaseType = TYPE_BYTE;
$$.TypeSign = SIGN_UNDEF;
$$.TypeSize = SIZE_UNDEF;
}
| KWHANDLET
{
$$.BaseType = TYPE_HANDLE_T;
$$.TypeSign = SIGN_UNDEF;
$$.TypeSize = SIZE_UNDEF;
}
| IntSpec
{
$$ = $1;
if( $$.BaseType == TYPE_UNDEF )
$$.BaseType = TYPE_INT;
if( $$.TypeSign == SIGN_UNDEF )
{
if( ($$.TypeSize != SIZE_SMALL) && ($$.TypeSize != SIZE_CHAR) )
$$.TypeSign = SIGN_SIGNED;
}
}
| CharSpecs
{
$$.BaseType = TYPE_INT;
$$.TypeSign = $1.TypeSign;
$$.TypeSize = SIZE_CHAR;
}
;
CharSpecs:
SignSpecs KWCHAR
{
$$.TypeSign = $1.TypeSign;
}
| KWCHAR
{
$$.TypeSign = SIGN_UNDEF;
}
;
IntSpec:
IntModifiers KWINT
{
BaseTypeSpecAnalysis( &($1), TYPE_INT );
}
| IntModifiers
| KWINT IntModifiers
{
$$ = $2;
$$.BaseType = TYPE_UNDEF;
}
| KWINT
{
$$.BaseType = TYPE_UNDEF;
$$.TypeSign = SIGN_UNDEF;
$$.TypeSize = SIZE_UNDEF;
}
;
IntModifiers:
IntSize
{
$$.TypeSign = SIGN_UNDEF;
$$.TypeSize = $1;
$$.BaseType = TYPE_UNDEF;
}
| SignSpecs
| IntSize SignSpecs
{
$$.TypeSign = $2.TypeSign;
$$.TypeSize = $1;
$$.BaseType = TYPE_UNDEF;
}
| SignSpecs IntSize
{
$$.TypeSign = $1.TypeSign;
$$.TypeSize = $2;
$$.BaseType = TYPE_UNDEF;
}
;
SignSpecs:
KWSIGNED
{
ParseError(SIGNED_ILLEGAL, (char *)0);
$$.BaseType = TYPE_UNDEF;
$$.TypeSign = SIGN_SIGNED;
$$.TypeSize = SIZE_UNDEF;
}
| KWUNSIGNED
{
$$.BaseType = TYPE_UNDEF;
$$.TypeSign = SIGN_UNSIGNED;
$$.TypeSize = SIZE_UNDEF;
}
;
IntSize:
KWHYPER
{
$$ = SIZE_HYPER;
}
| KWLONG KWLONG
{
$$ = SIZE_LONGLONG;
}
| KWINT64
{
$$ = SIZE_HYPER;
}
| KWLONG
{
$$ = SIZE_LONG;
}
| KWSHORT
{
$$ = SIZE_SHORT;
}
| KWSMALL
{
$$ = SIZE_SMALL;
}
;
PhantomPushSymtab:
{
/**
** We just obtained a starter for a new scope. Push the
** symbol table to the next level for the rest of the including
** production
**/
pSymTblMgr->PushSymLevel( &pCurSymTbl );
}
/* START TAGGED SPEC */
TaggedSpec:
TaggedStructSpec
| TaggedUnionSpec
;
/* START TAGGED STRUCT */
TaggedStructSpec:
KWSTRUCT OptionalTag '{' PhantomPushSymtab StructDeclarationList '}'
{
/**
** The entire struct was sucessfully reduced. Attach the fields as
** members of the struct. Insert a new symbol table entry for the
** struct and attach the lower scope of the symbol table to it.
** Check for dupliate structure definition
**/
BOOL fFound = FALSE;
BOOL fStructIsForwardDecl = FALSE;
node_struct * pStruct;
SymTable * pSymLowerScope = pCurSymTbl;
SymKey SKey( $2, NAME_TAG );
/**
** discard the inner symbol table contents (unless it had fwds)
**/
pCurSymTbl->DiscardScope();
/**
** restore the symbol table level
**/
pSymTblMgr->PopSymLevel( &pCurSymTbl );
/**
** if this is a duplicate definition, dont do anything. Note that
** the struct tag name shares the global name space with enum and
** union tag names.
**/
pStruct = (node_struct *) pBaseSymTbl->SymSearch( SKey );
if( fFound = ( pStruct != (node_struct *)NULL ) )
fStructIsForwardDecl = (pStruct->NodeKind() == NODE_FORWARD || pStruct->NodeKind() == NODE_HREF);
if( fFound && !fStructIsForwardDecl )
{
ParseError( DUPLICATE_DEFINITION, $2 );
pStruct = (node_struct *)pErrorTypeNode;
}
else
{
/**
** this is a valid entry. Build the graph for it and
** enter into symbol table. If the struct entry was present as
** a forward decl, delete it
**/
if( fStructIsForwardDecl )
{
pBaseSymTbl->SymDelete( SKey );
}
pStruct = new node_struct( $2 );
pStruct->SetMembers( $5 );
pStruct->SetZeePee( CurrentZp );
pBaseSymTbl->SymInsert( SKey, pSymLowerScope, pStruct );
CheckGlobalNamesClash( SKey );
}
$$.pNode = pStruct;
$$.modifiers = 0;
}
| KWSTRUCT Tag
{
/**
** This is the invocation of a struct. If the struct was not
** defined as yet, then return a forward declarator node. The
** semantics will register the forward declaration and resolve it.
** But there is a loop hole in this. If we do not enter the struct into
** the symbol table, the user may define a union/enum of the same name.
** We will let him, since we do not yet have an entry in the symbol
** table. We will then never check for duplication, since the parser
** is the only place we check for this. We will then generate wrong
** code, with the struct and a union/enum with the same name !! The
** solution is to enter a symbol entry with a fdecl node as the type
** graph of the struct.
**/
SymKey SKey( $2, NAME_TAG );
named_node * pNode = pBaseSymTbl->SymSearch( SKey );
if( !pNode || (pNode->NodeKind() == NODE_FORWARD ) )
{
pNode = new node_forward( SKey, pBaseSymTbl );
pNode->SetSymName( $2 );
}
$$.pNode = pNode;
$$.modifiers = SetModifierBit(ATTR_TAGREF);
}
;
OptionalTag:
Tag
| /* Empty */
{
$$ = GenCompName();
}
;
Tag:
IDENTIFIER
{
$$ = $1;
}
| TypeName
{
//$$ = $1;
$$ = $1->GetCurrentSpelling();
}
;
StructDeclarationList:
StructDeclarationList MemberDeclaration
{
$$.Merge( $2 );
}
| MemberDeclaration
;
MemberDeclaration:
OptionalAttrList DeclarationSpecifiers MemberDeclaratorList ';'
{
/**
** This is a complete field declaration. For each declarator,
** set up a field with the basic type as the declaration specifier,
** apply the field attributes, and add to the list of fields for the
** struct / union
** field
**/
class _DECLARATOR * pDec;
node_skl * pType;
DECLARATOR_LIST_MGR DeclList( $3 );
$$.Init();
while( pDec = DeclList.DestructiveGetNext() )
{
node_field * pField = (node_field *) pDec->pHighest;
/**
** if the field was a bit field, we need to set up some additional
** info.
**/
pType = $2.pNode;
pDec->pLowest->SetChild( pType );
/**
** Apply the field attributes and set the field as part of the
** list of fields of the struct/union
**/
if ( $1.NonNull() )
{
pField->AddAttributes( $1 );
}
/**
** similarly, apply the remnant attributes collected from
** declaration specifiers, to the declarator
**/
if( $2.modifiers )
{
pDec->pLowest->SetModifiers( $2.modifiers );
};
/**
** shove the type graph up
**/
$$.Add( pField );
}
}
;
/* START UNION */
TaggedUnionSpec:
KWUNION OptionalTag '{' PhantomPushSymtab UnionBody '}'
{
/**
** The union bosy has been completely reduced. Attach the fields as
** members, insert a new symbol table entry for the union
**/
BOOL fFound = FALSE;
BOOL fUnionIsForwardDecl = FALSE;
node_union * pUnion;
SymTable * pSymLowerScope = pCurSymTbl;
SymKey SKey( $2, NAME_UNION );
/**
** discard the inner symbol table contents (unless it had fwds)
**/
pCurSymTbl->DiscardScope();
/**
** restore the symbol table level
**/
pSymTblMgr->PopSymLevel( &pCurSymTbl );
/**
** if this is a duplicate definition, dont do anything, else
** enter into the symbol table, attach members. Note that the
** symbol table search is actually a search for the tag becuase
** the union tag shares the same name as the struct/enum names
**/
pUnion = (node_union *)pBaseSymTbl->SymSearch( SKey );
if( fFound = (pUnion != (node_union *) NULL ) )
fUnionIsForwardDecl = ( pUnion->NodeKind() == NODE_FORWARD || pUnion->NodeKind() == NODE_HREF );
if( fFound && !fUnionIsForwardDecl )
{
ParseError( DUPLICATE_DEFINITION, $2 );
pUnion = (node_union *)pErrorTypeNode;
}
else
{
/**
** This is a valid entry, build the type graph and insert into
** the symbol table. Delete the entry first if it was a forward
** decl.
**/
pUnion = new node_union( $2 );
pUnion->SetMembers( $5 );
if( fUnionIsForwardDecl )
{
pBaseSymTbl->SymDelete( SKey );
}
pBaseSymTbl->SymInsert( SKey, pSymLowerScope, pUnion );
CheckGlobalNamesClash( SKey );
}
/**
** pass this union up
**/
pUnion->SetZeePee( CurrentZp );
$$.pNode = pUnion;
$$.modifiers = 0;
}
| KWUNION Tag
{
/**
** this is an invocation of the union. If the union was not defined
** then return a forward declarator node as the type node. The
** semantics will register the forward declaration and resolve it
** later. See TaggedStruct production for an explanation why we want to
** enter even a forward declaration into the symbol table.
**/
SymKey SKey( $2, NAME_UNION );
named_node * pNode = pBaseSymTbl->SymSearch( SKey );
if( !pNode || (pNode->NodeKind() == NODE_FORWARD ) )
{
pNode = new node_forward( SKey, pBaseSymTbl );
pNode->SetSymName( $2 );
}
$$.pNode = pNode;
$$.modifiers = SetModifierBit(ATTR_TAGREF);
}
| KWUNION OptionalTag NidlUnionSwitch '{' PhantomPushSymtab NidlUnionBody '}'
{
/**
** The union body has been completely reduced. Attach the fields as
** members, insert a new symbol table entry for the union
**/
BOOL fFound = FALSE;
BOOL fStructIsForwardDecl = FALSE;
node_en_union * pUnion;
SymTable * pSymLowerScope = pCurSymTbl;
/**
** discard the inner symbol table contents (unless it had fwds)
**/
pCurSymTbl->DiscardScope();
/**
** restore the symbol table level
**/
pSymTblMgr->PopSymLevel( &pCurSymTbl );
pUnion = new node_en_union( GenCompName() );
pUnion->SetMembers( $6 );
SymKey SKey( pUnion->GetSymName(), NAME_UNION );
pBaseSymTbl->SymInsert( SKey, pSymLowerScope, pUnion );
CheckGlobalNamesClash( SKey );
//
// The union is inserted into the base symbol table.
// Now insert into the base symbol table, a new struct entry
// corresponding to the struct entry that the encapsulated union
// results in.
//
pSymTblMgr->PushSymLevel( &pCurSymTbl );
SIBLING_LIST Fields;
node_field * pSwitchField = (node_field *) $3.pNode;
node_field * pUnionField = new node_field;
node_switch_type * pSwType = new node_switch_type(
pSwitchField->GetChild() );
if( IsTempName( $3.pName ) )
$3.pName = "tagged_union";
pUnionField->SetSymName( $3.pName );
pUnionField->SetChild( pUnion );
Fields.Init( pSwitchField );
Fields.Add( pUnionField );
//
// apply the switch_is attribute to the union field.
//
pUnionField->SetAttribute( $3.pSwitch );
// and the switch_type attribute to the union itself
pUnion->SetAttribute( pSwType );
//
// current symbol table is pointing to a new scope. Enter the two
// fields into this scope.
//
SKey.SetKind( NAME_MEMBER );
SKey.SetString( pSwitchField->GetSymName() );
pCurSymTbl->SymInsert( SKey, (SymTable *)0, pSwitchField );
CheckGlobalNamesClash( SKey );
SKey.SetString( pUnionField->GetSymName() );
pCurSymTbl->SymInsert( SKey, (SymTable *)0, pUnionField );
CheckGlobalNamesClash( SKey );
pSymLowerScope = pCurSymTbl;
pSymTblMgr->PopSymLevel( &pCurSymTbl );
//
// create a new structure entry and enter into the symbol table.
//
node_struct * pStruct;
SKey.SetKind( NAME_UNION );
SKey.SetString( $2 );
pStruct = (node_struct *)pBaseSymTbl->SymSearch( SKey );
if( fFound = ( pStruct != (node_struct *)NULL ) )
fStructIsForwardDecl = (pStruct->NodeKind() == NODE_FORWARD || pStruct->NodeKind() == NODE_HREF );
if( fFound && !fStructIsForwardDecl )
{
ParseError( DUPLICATE_DEFINITION, $2 );
pStruct = (node_struct *)pErrorTypeNode;
}
else
{
/**
** this is a valid entry. Build the graph for it and
** enter into symbol table. If the struct entry was present as
** a forward decl, delete it
**/
// enter the struct as a union.
SKey.SetKind( NAME_UNION );
SKey.SetString( $2 );
if( fStructIsForwardDecl )
{
pBaseSymTbl->SymDelete( SKey );
}
pStruct = new node_en_struct( $2 );
pStruct->SetMembers( Fields );
pStruct->SetZeePee( CurrentZp );
pBaseSymTbl->SymInsert( SKey, pSymLowerScope, pStruct );
CheckGlobalNamesClash( SKey );
}
pUnion->SetZeePee( CurrentZp );
$$.pNode = pStruct;
$$.modifiers = 0;
}
;
UnionBody:
UnionCases
;
UnionCases:
UnionCases UnionCase
{
($$ = $1).Merge( $2 );
}
| UnionCase
;
UnionCase:
UnionCaseLabel MemberDeclaration
{
/**
** for each of the fields, attach the case label attribute.
**/
named_node * pNode;
SIBLING_ITER MemIter( $2 );
$$ = $2;
while( pNode = MemIter.Next() )
{
pNode->SetAttribute( $1 );
}
}
| UnionCaseLabel ';'
{
/**
** An empty arm. Allocate a field with a node_error as a basic type
** and set the attribute as a case label
**/
node_field * pField = new node_field( GenTempName() );
pField->SetChild( pErrorTypeNode );
pField->SetAttribute( $1 );
/**
** Generate a list of union fields and add this to the list of
** union fields
**/
$$.Init( pField );
}
| MemberDeclaration
{
/**
** A member declaration without a case label
**/
$$ = $1;
}
| DefaultCase
;
UnionCaseLabel:
'[' KWCASE '(' ConstantExprs ')' ']'
{
$$ = new node_case( $4 );
}
;
DefaultCase:
'[' KWDEFAULT ']' MemberDeclaration
{
named_node * pNode;
SIBLING_ITER MemIter( $4 );
$$ = $4;
while( pNode = MemIter.Next() )
{
pNode->SetAttribute( ATTR_DEFAULT );
}
}
| '[' KWDEFAULT ']' ';'
{
/**
** This is a default with an empty arm. Set up a dummy field.
** The upper productions will then mark set field with a
** default attribute during semantic analysis. The type of this field
** is set up to be an error node for uniformity.
**/
node_field * pField = new node_field( GenTempName() );
pField->SetAttribute( ATTR_DEFAULT );
pField->SetChild( pErrorTypeNode );
$$.Init( pField );
}
;
NidlUnionSwitch:
SwitchSpec
{
$$ = $1;
$$.pName = GenCompName();
}
| SwitchSpec UnionName
{
$$ = $1;
$$.pName = $2;
}
;
NidlUnionBody:
NidlUnionCases
{
$$ = $1.CaseList;
if( $1.DefCount > 1 )
ParseError( TWO_DEFAULT_CASES, (char *)0 );
}
;
NidlUnionCases:
NidlUnionCases NidlUnionCase
{
$$.DefCount += $2.DefCount;
$$.CaseList.Merge( $2.CaseList );
}
| NidlUnionCase
;
NidlUnionCase:
NidlUnionCaseLabelList NidlMemberDeclaration
{
named_node * pNode;
//
// set the case and default attributes.
//
$$.CaseList = $2;
if( $1.pExprList && $1.pExprList->GetCount() )
{
SIBLING_ITER CaseIter( $2 );
while( pNode = CaseIter.Next() )
{
pNode->SetAttribute( new node_case( $1.pExprList ));
}
}
//
// pick up default attribute. pick up the count of number of
// times the user specified default so that we can report the
// error later.
// Let the default case list count travel upward to report an
// error when the total list of case labels is seen.
//
if( $1.pDefault && ( $$.DefCount = $1.DefCount ) )
{
SIBLING_ITER CaseIter( $2 );
while( pNode = CaseIter.Next() )
{
pNode->SetAttribute( $1.pDefault );
}
}
}
;
NidlMemberDeclaration:
MemberDeclaration
| ';'
{
node_field * pNode = new node_field( GenTempName() );
pNode->SetChild( pErrorTypeNode );
$$.Init( pNode );
}
;
NidlUnionCaseLabelList:
NidlUnionCaseLabelList NidlUnionCaseLabel
{
if( $2.pExpr )
$$.pExprList->SetPeer( $2.pExpr );
if( !($$.pDefault) )
$$.pDefault = $2.pDefault;
if( $2.pDefault )
$$.DefCount++;
}
| NidlUnionCaseLabel
{
$$.pExprList = new expr_list;
if( $1.pExpr )
$$.pExprList->SetPeer( $1.pExpr );
if( $$.pDefault = $1.pDefault)
{
$$.DefCount = 1;
}
}
;
NidlUnionCaseLabel:
KWCASE ConstantExpr ':'
{
$$.pExpr = $2;
$$.pDefault = 0;
}
| KWDEFAULT ':'
{
$$.pExpr = 0;
$$.pDefault = new battr( ATTR_DEFAULT );
}
;
SwitchSpec:
KWSWITCH '(' SwitchTypeSpec IDENTIFIER ')'
{
node_field * pField = new node_field( $4 );
$$.pSwitch = new node_switch_is( new expr_variable( $4, pField ));
$$.pNode = pField;
pField->SetChild( $3 );
pField->SetModifiers( SetModifierBit( ATTR_TAGREF ) );
}
;
UnionName:
IDENTIFIER
;
/**
** NIDL UNION END
**/
ConstantExprs:
ConstantExprs ',' ConstantExpr
{
$$->SetPeer( $3 );
}
| ConstantExpr
{
$$ = new expr_list;
$$->SetPeer( $1 );
}
;
/* END UNION */
TypeQualifier:
KWVOLATILE
{
$$ = SetModifierBit(ATTR_VOLATILE);
}
| KWCONST
{
$$ = SetModifierBit(ATTR_CONST);
}
| KW_C_INLINE
{
$$ = SetModifierBit(ATTR_C_INLINE);
}
;
MemberDeclaratorList:
MemberDeclarator
{
$$.Init( $1 );
}
| MemberDeclaratorList ',' MemberDeclarator
{
$$ = $1;
$$.Add( $3 );
}
;
MemberDeclarator:
Declarator
{
/**
** a declarator without bit fields specified; a plain field.
**/
if ( ($1.pHighest == NULL)
|| ( $1.pHighest->NodeKind() != NODE_ID ))
{
node_def_fe * pDef = new node_def_fe( GenTempName(), pErrorTypeNode );
// gaj - report error
ParseError( BENIGN_SYNTAX_ERROR, "expecting a declarator");
}
else
{
// convert top node of declarator chain to node_field
// and add the field to the symbol table
node_field * pField = new node_field(
(node_id_fe *) $1.pHighest );
char * pName = pField->GetSymName();
SymKey SKey( pName, NAME_MEMBER );
$$.pHighest = pField;
// if the top node was the only node, set pLowest accordingly
$$.pLowest = ( $1.pLowest == $1.pHighest ) ?
pField : $1.pLowest ;
delete (node_id_fe *) $1.pHighest;
if( !pCurSymTbl->SymInsert( SKey, (SymTable *)NULL, pField ) )
{
ParseError( DUPLICATE_DEFINITION, pName );
}
else
CheckGlobalNamesClash( SKey );
};
}
| ':' ConstantExpr
{
/**
** This is a declarator specified without the field name
**/
node_bitfield * pField = new node_bitfield();
char * pName = GenTempName();
pField->SetSymName(pName);
$$.pHighest = pField;
$$.pLowest = pField;
// add the field to the symbol table
SymKey SKey( pName, NAME_MEMBER );
if( !pCurSymTbl->SymInsert( SKey, (SymTable *)NULL, pField ) )
{
ParseError( DUPLICATE_DEFINITION, pName );
}
else
CheckGlobalNamesClash( SKey );
pField->fBitField = (unsigned char)$2->Evaluate();
}
| Declarator ':' ConstantExpr
{
/**
** The complete bit field specification.
**/
if ( ($1.pHighest == NULL)
|| ( $1.pHighest->NodeKind() != NODE_ID ))
{
// gaj - report error
}
else
{
// convert top node of declarator chain to node_field
node_bitfield * pField = new node_bitfield( (node_id_fe *) $1.pHighest );
char * pName = pField->GetSymName();
$$.pHighest = pField;
// if the top node was the only node, set pLowest accordingly
$$.pLowest = ( $1.pLowest == $1.pHighest ) ? pField : $1.pLowest;
delete (node_id_fe *) $1.pHighest;
// add the field to the symbol table
SymKey SKey( pName, NAME_MEMBER );
if( !pCurSymTbl->SymInsert( SKey, (SymTable *)NULL, pField ) )
{
ParseError( DUPLICATE_DEFINITION, pName );
}
else
CheckGlobalNamesClash( SKey );
pField->fBitField = (unsigned char)$3->Evaluate();
}
}
| /** Empty **/
{
// this is used for unnamed nested struct references
node_field * pField = new node_field();
char * pName = GenTempName();
pField->SetSymName( pName);
$$.pHighest = pField;
$$.pLowest = pField;
}
;
OptionalInitDeclaratorList:
InitDeclaratorList
| /* Empty */
{
$$.Init();
}
;
InitDeclaratorList:
InitDeclarator
{
$$.Init( $1 );
}
| InitDeclaratorList ',' InitDeclarator
{
$$ = $1;
$$.Add( $3 );
}
;
InitDeclarator:
Declarator
{
node_id_fe * pID = (node_id_fe *) $1.pHighest;
/**
** If the top node of the declarator is null, create a dummy ID
** but not if the top is a proc...
**/
if ( ($1.pHighest == NULL)
|| ( ( $1.pHighest->NodeKind() != NODE_ID )
&& ( $1.pHighest->NodeKind() != NODE_PROC) ) )
{
pID = new node_id_fe( GenTempName() );
pID->SetChild( $1.pHighest );
$$.pHighest = pID;
$$.pLowest = ( $1.pLowest ) ? $1.pLowest : pID; // in case of null
};
/**
** and add the id to the symbol table
** for node_proc's, leave original in symbol table
**/
if ( $1.pHighest->NodeKind() != NODE_PROC )
{
char * pName = pID->GetSymName();
SymKey SKey( pName, NAME_ID );
if( !pCurSymTbl->SymInsert( SKey, (SymTable *)NULL, pID ) )
{
ParseError( DUPLICATE_DEFINITION, pName );
}
else
CheckGlobalNamesClash( SKey );
}
};
| Declarator '=' Initializer
{
if ( ($1.pHighest == NULL)
|| ( $1.pHighest->NodeKind() != NODE_ID ))
{
// gaj - report error
}
else
{
node_id_fe * pID = (node_id_fe *) $1.pHighest;
// fill in initializer
pID->pInit = $3;
$$ = $1;
// and add the id to the symbol table
char * pName = pID->GetSymName();
SymKey SKey( pName, NAME_ID );
if( !pCurSymTbl->SymInsert( SKey, (SymTable *)NULL, pID ) )
{
ParseError( DUPLICATE_DEFINITION, pName );
}
else
CheckGlobalNamesClash( SKey );
};
}
;
TypedefDeclaratorList:
';'
{
$$.Init();
}
| TypedefDeclaratorListElement ';'
;
TypedefDeclaratorListElement:
TypedefDeclarator
{
$$.Init( $1 );
}
| TypedefDeclaratorListElement ',' TypedefDeclarator
{
$$ = $1;
$$.Add( $3 );
}
;
TypedefDeclarator:
Declarator
{
node_def_fe * pDef;
char * pName;
if ($1.pHighest == NULL)
{
// gaj - report error
}
else if ( $1.pHighest->NodeKind() == NODE_PROC )
{
// build new node_def and attach to top
node_proc * pProc = (node_proc *) $1.pHighest;
pName = pProc->GetSymName();
pDef = new node_def_fe( (node_proc *) $1.pHighest );
pDef->SetSymName(pName);
pDef->SetChild( $1.pHighest );
if ( !strcmp(pName, "HRESULT") || !strcmp(pName, "SCODE") )
pDef->SetIsHResultOrSCode();
$$.pHighest = pDef;
$$.pLowest = $1.pLowest;
SymKey SkeyOld( pName, NAME_PROC );
pInterfaceInfoDict->GetInterfaceProcTable()->SymDelete( SkeyOld );
SymKey SKey( pName, NAME_DEF );
if( !pCurSymTbl->SymInsert( SKey, (SymTable *)NULL, pDef ) )
{
ParseError( DUPLICATE_DEFINITION, pName );
}
else
CheckGlobalNamesClash( SKey );
}
else if ( $1.pHighest->NodeKind() == NODE_ID )
{
// convert top node of declarator chain to node_def
// and add the def to the symbol table
node_def_fe * pDef = new node_def_fe( (node_id_fe *) $1.pHighest );
char * pName = pDef->GetSymName();
SymKey SKey( pName, NAME_DEF );
if ( !pName )
pDef->SetSymName( GenTempName() );
if ( !strcmp(pName, "HRESULT") || !strcmp(pName, "SCODE") )
pDef->SetIsHResultOrSCode();
$$.pHighest = pDef;
// if the top node was the only node, set pLowest accordingly
$$.pLowest = ( $1.pLowest == $1.pHighest ) ? pDef : $1.pLowest;
delete (node_id_fe *) $1.pHighest;
named_node * pFound;
// Allow redefinition of imported types.
pFound = pBaseSymTbl->SymSearch( SKey );
// if (pFound && ( pFound->NodeKind() == NODE_HREF ))
if (pFound && ( NULL != pFound->GetDefiningFile() ))
{
pBaseSymTbl->SymDelete( SKey );
}
if(!pCurSymTbl->SymInsert( SKey, (SymTable *)NULL, pDef ))
{
//
// allow benign redef of wchar_t & error_status_t.
//
if ( ( strcmp( pName, "wchar_t" ) != 0 ) &&
( strcmp( pName, "error_status_t" ) != 0 ) )
{
ParseError( DUPLICATE_DEFINITION, pName );
}
}
else
{
CheckGlobalNamesClash( SKey );
}
};
}
;
OptionalDeclarator:
Declarator
| /* Empty */
{
$$.Init();
}
;
/***
*** declarators are the last part of declarations; e.g. with
*** long *p, **q, f(long abc);
*** each of "*p", "**q", and "f(long abc)" are declarators.
***
*** As declarators are built, they are just dangling parts of the
*** typegraph, so we pass the topmost node and the lowest node (with
*** no child set yet)
***
***/
Declarator:
OptionalModifierList Declarator2
{
// note that leading modifiers eventually attach to the
// lowest node of the declarator
$2.pLowest->SetModifiers( $1 );
$$ = $2;
}
| Pointer
| Pointer OptionalModifierList Declarator2
{
// point dangling declarator2 lowest to pointer highest,
// set modifiers on Declarator2
// return declarator2 highest with pointer lowest
$3.pLowest->SetModifiers($2);
$3.pLowest->SetChild($1.pHighest);
$$.pLowest = $1.pLowest;
$$.pHighest = $3.pHighest;
}
;
/***
*** Note that modifiers get stored with the pointer or declarator2 FOLLOWING
*** the attribute
***
*** Note also that pHighest and pLowest are guaranteed to be non-null
*** for pointers.
***/
Pointer:
OptionalModifierList '*'
{
node_pointer * pPtr = new node_pointer( (node_pointer *) NULL );
pPtr->SetModifiers( $1 );
#ifdef gajdebug8
printf("\t\t attaching modifier to lone ptr: %08x\n",$1);
#endif
// create node_pointer with modifierlist
$$.Init( pPtr );
}
| Pointer OptionalModifierList '*'
{
node_pointer * pPtr = new node_pointer( $1.pHighest );
pPtr->SetModifiers( $2 );
// create node_pointer, set child, apply modifierlist to it
$$.Init( pPtr, $1.pLowest );
}
;
OptionalModifierList:
ModifierList
| /* Empty */
{
$$ = 0;
}
;
ModifierList:
Modifier
| ModifierList Modifier
{
$$ = $1 | $2;
}
;
Modifier:
PtrModifier
| FuncModifier
| TypeQualifier
;
PtrModifier:
MSCFAR
{
$$ = SetModifierBit(ATTR_FAR);
ParseError( BAD_CON_MSC_CDECL, "__far" );
}
| MSCNEAR
{
$$ = SetModifierBit(ATTR_NEAR);
ParseError( BAD_CON_MSC_CDECL, "__near" );
}
| MSCHUGE
{
$$ = SetModifierBit(ATTR_HUGE);
ParseError( BAD_CON_MSC_CDECL, "__huge" );
}
| MSCUNALIGNED
{
$$ = SetModifierBit(ATTR_MSCUNALIGNED);
ParseError( BAD_CON_MSC_CDECL, "unaligned" );
}
;
FuncModifier:
MSCPASCAL
{
$$ = SetModifierBit(ATTR_PASCAL);
ParseError( BAD_CON_MSC_CDECL, "__pascal" );
}
| MSCFORTRAN
{
$$ = SetModifierBit(ATTR_FORTRAN);
ParseError( BAD_CON_MSC_CDECL, "__fortran" );
}
| MSCCDECL
{
$$ = SetModifierBit(ATTR_CDECL);
ParseError( BAD_CON_MSC_CDECL, "__cdecl" );
}
| MSCSTDCALL
{
$$ = SetModifierBit(ATTR_STDCALL);
ParseError( BAD_CON_MSC_CDECL, "__stdcall" );
}
| MSCLOADDS /* potentially interesting */
{
$$ = SetModifierBit(ATTR_LOADDS);
ParseError( BAD_CON_MSC_CDECL, "__loadds" );
}
| MSCSAVEREGS
{
$$ = SetModifierBit(ATTR_SAVEREGS);
ParseError( BAD_CON_MSC_CDECL, "__saveregs" );
}
| MSCFASTCALL
{
$$ = SetModifierBit(ATTR_FASTCALL);
ParseError( BAD_CON_MSC_CDECL, "__fastcall" );
}
| MSCSEGMENT
{
$$ = SetModifierBit(ATTR_SEGMENT);
ParseError( BAD_CON_MSC_CDECL, "__segment" );
}
| MSCINTERRUPT
{
$$ = SetModifierBit(ATTR_INTERRUPT);
ParseError( BAD_CON_MSC_CDECL, "__interrupt" );
}
| MSCSELF
{
$$ = SetModifierBit(ATTR_SELF);
ParseError( BAD_CON_MSC_CDECL, "__self" );
}
| MSCEXPORT
{
$$ = SetModifierBit(ATTR_EXPORT);
ParseError( BAD_CON_MSC_CDECL, "__export" );
}
| MSCDECLSPEC '(' MSCDLLIMPORT ')'
{
$$ = SetModifierBit(ATTR_DLLIMPORT);
ParseError( BAD_CON_MSC_CDECL, "__declspec(dllimport)" );
}
| MSCDECLSPEC '(' MSCDLLEXPORT ')'
{
$$ = SetModifierBit(ATTR_DLLEXPORT);
ParseError( BAD_CON_MSC_CDECL, "__declspec(dllexport)" );
}
| MSCEMIT NUMERICCONSTANT
{
$$ = SetModifierBit(ATTR_NONE);
ParseError( BAD_CON_MSC_CDECL, "__emit" );
}
;
/* Declarator2 is whatever is left of the declarator after all the
pointer stuff has been eaten
*/
Declarator2:
'(' Declarator ')'
{
$$ = $2;
}
| Declarator2 PhantomPushSymtab ParamsDecl2 OptionalConst
{
node_proc * pProc;
char * pName;
SymTable * pParamSymTbl = pCurSymTbl;
BOOL IsProc = TRUE;
/**
** If the declarator was an ID and just a simple ID (basic type is
** a null), we have just seen a declaration of a procedure.
** If we saw an ID which had a basic type, then the ID is a declarator
** whose basic type is a procedure (like in a typedef of a proc or
** pointer to proc).
**/
/**
** if the node is a simple ID, then copy node details, else,
** set the basic type of the declarator as this proc, and set the
** procs name to a temporary.
**/
// gaj - check for null...
if ( ( $1.pHighest == $1.pLowest)
&& ($1.pLowest->NodeKind() == NODE_ID ) )
{
pProc = new node_proc( ImportLevel,
IS_CUR_INTERFACE_LOCAL(),
(node_id_fe *) $1.pHighest);
pName = pProc->GetSymName();
$$.pHighest = pProc;
$$.pLowest = pProc;
delete (node_id_fe *) $1.pHighest;
}
else
{
pProc = new node_proc( ImportLevel,
IS_CUR_INTERFACE_LOCAL() );
pProc->SetSymName( pName = GenTempName() );
$1.pLowest->SetChild( pProc );
$$.pHighest = $1.pHighest;
$$.pLowest = pProc;
IsProc = FALSE;
}
/**
** Set members of the procedure node as the parameter nodes.
**/
pProc->SetMembers( $3 );
/**
** discard the inner symbol table contents (unless it had fwds)
**/
pCurSymTbl->DiscardScope();
/**
** restore the symbol tables scope to normal, since we have already
** picked up a pointer to the next scope symbol table.
**/
pSymTblMgr->PopSymLevel( &pCurSymTbl );
/**
** if this proc was entered into our symbol table, then this is a
** redeclaration.But wait ! This is true only if the importlevel is 0
** I.e , if there was a proc of the same name defined at an import
** level greater, we dont care. (Actually, we must really check
** signatures, so that valid redeclarations are ok, with a warning )
**/
if( IsProc )
{
SymKey SKey( pName , NAME_PROC );
//if ( ImportLevel == 0 )
{
if( !pInterfaceInfoDict->GetInterfaceProcTable()->
SymInsert( SKey, pParamSymTbl, pProc ) )
{
ParseError( DUPLICATE_DEFINITION, pName );
}
}
/********
else
CheckGlobalNamesClash( SKey );
********/
}
/**
** finally, for the const support, if the optional const is true
** apply the const attribute on the proc
**/
pProc->SetModifiers( $4 );
}
| '(' ')' OptionalConst
{
/**
** this is an abstract declarator for a procedure. Generate a
** new proc node with a temp name, enter the name into the symbol
** table.
**/
char * pName = GenTempName();
SymKey SKey( pName, NAME_PROC );
node_proc * pProc = new node_proc( ImportLevel,
IS_CUR_INTERFACE_LOCAL() );
$$.Init ( pProc );
pProc->SetSymName( pName );
/**
** enter this into the symbol table , only if we are in the base idl
** file, not an imported file.
**/
if( ImportLevel == 0 )
pInterfaceInfoDict->GetInterfaceProcTable()->SymInsert( SKey,
(SymTable *)NULL,
(named_node *) $$.pHighest );
/**
** finally, for the const support, if the optional const is true
** apply the const attribute on the proc
**/
pProc->SetModifiers( $3 );
}
| Declarator2 ArrayDecl
{
/**
** The basic type of the declarator is the array
**/
$$.pHighest = $1.pHighest;
$1.pLowest->SetChild( $2.pHighest );
$$.pLowest = $2.pLowest;
}
| ArrayDecl
{
$$ = $1;
}
| IDENTIFIER
{
char * pName = $1;
if ( !pName )
pName = GenTempName();
$$.Init( new node_id_fe( pName ) );
}
| TypeName
{
/**
** This production ensures that a declarator can be the same name
** as a typedef. The lexer will return all lexemes which are
** typedefed as TYPENAMEs and we need to permit the user to specify
** a declarator of the same name as the type name too! This conflict
** arises only in the declarator productions, so this is an easy way
** to support it.
**/
$$.Init( new node_id_fe( $1->GetCurrentSpelling() ) );
}
;
/* Note: the omition of param_decl2 above precludes
int foo( int (bar) ); a real ambiguity of C. If bar is a predefined
type then the parameter of foo can be either:
1. a function with a bar param, and an int return value, as in
int foo( int func(bar) );
2. A function with an int parameter by the name of bar, as in
int foo( int bar );
*/
ParamsDecl2:
'(' ')'
{
/**
** this production corresponds to no params to a function.
**/
/**
** Return it as an empty list of parameters
**/
$$.Init( NULL );
}
| '(' ParameterTypeList ')'
{
$$ = $2;
}
;
ParameterTypeList:
ParameterList
| ParameterList ',' DOTDOT '.'
{
/**
** This is meaningless in rpc, but we consume it and report an
** error during semantics, if a proc using this param ever gets
** remoted. We call this a param node with the name "...". And set its
** basic type to an error node, so that a param is properly terminated.
** The backend can emit a "..." for the name, so that this whole
** thing is essentially transparent to it.
**/
if ( 1 ) //ImportLevel == 0 ) <- change back when imported params not needed
{
node_param * pParam = new node_param;
pParam->SetSymName( "..." );
pParam->SetChild( pErrorTypeNode );
$$ = $1;
$$.Add( pParam );
}
}
;
ParameterList:
ParameterDeclaration
{
$$.Init( $1 );
}
| ParameterList ',' ParameterDeclaration
{
if ( $3 && $1.NonNull() )
{
$$.Add( (named_node *) $3 );
}
else
{
// tbd - error if later parameters are void
}
}
;
ParameterDeclaration:
OptionalAttrList DeclarationSpecifiers Declarator
{
if (0) // ( ImportLevel > 0 )
{
if ( $3.pHighest->NodeKind() == NODE_ID )
delete (node_id_fe *) $3.pHighest;
$$ = NULL;
}
else
{
node_param * pParam;
char * pName;
node_id_fe * pOriginal = NULL;
/**
** Apply the declaration specifier to the declarator as a basic type
**/
$3.pLowest->SetChild( $2.pNode );
/**
** apply any attributes specified to the declaration specifiers
**/
$3.pLowest->SetModifiers( $2.modifiers );
/**
** if the declarator was just an id, then we have to copy the
** node details over, else set the basic type of the param to
** the declarator
**/
if ( $3.pHighest->NodeKind() == NODE_ID )
{
pOriginal = (node_id_fe *) $3.pHighest;
pParam = new node_param( pOriginal );
}
else
{
pParam = new node_param;
pParam->SetChild( $3.pHighest );
};
/**
** prepare for symbol table entry.
**/
if( !(pName = pParam->GetSymName()) )
{
pParam->SetSymName(pName = GenTempName() );
}
if ( IsTempName( pParam->GetSymName() ) )
ParseError( ABSTRACT_DECL, (char *)NULL );
SymKey SKey( pName, NAME_MEMBER );
/**
** enter the parameter into the symbol table.
** If the user specified more than one param with the same name,
** report an error, else insert the symbol into the table
**/
if( !pCurSymTbl->SymInsert( SKey, (SymTable *)NULL, pParam ) )
{
//
// dont complain on another param of name void. This check is
// made elsewhere.
//
if( strcmp( pName, "void" ) != 0 )
ParseError( DUPLICATE_DEFINITION, pName );
}
else
CheckGlobalNamesClash( SKey );
if ( $1 )
{
pParam->AddAttributes( $1 );
}
// clean up any old node_id
if ( pOriginal )
delete pOriginal;
/**
** return the node back
**/
$$ = pParam;
}
}
| OptionalAttrList DeclarationSpecifiers
{
/**
** This is the case when the user specified a simple abstract
** declaration eg proc1( short ). In other words, the declarator is
** optional. Abstract declarators are illegal in osf mode.
** If the declaration specifier is a void then skip the parameter
**/
if( // ( ImportLevel > 0 ) ||
( $2.pNode->NodeKind() == NODE_VOID ) )
{
$$ = NULL;
}
else
{
char * pName = GenTempName();
SymKey SKey( pName, NAME_MEMBER );
node_param * pParam = new node_param;
pParam->SetSymName( pName );
pParam->SetChild( $2.pNode );
ParseError( ABSTRACT_DECL, (char *)NULL );
/**
** enter into symbol table, just like anything else.
**/
if( !pCurSymTbl->SymInsert( SKey, (SymTable *)NULL, pParam ) )
{
ParseError( DUPLICATE_DEFINITION, pName );
}
/**
** apply any attributes specified to the declaration specifiers
**/
pParam->SetModifiers( $2.modifiers );
if ( $1 )
{
pParam->AddAttributes( $1 );
}
$$ = pParam;
}
}
;
OptionalConst:
KWCONST
{
$$ = SetModifierBit(ATTR_PROC_CONST);
}
| /* empty */
{
$$ = 0;
}
;
ArrayDecl:
ArrayDecl2
{
$$.Init( new node_array( $1.LowerBound, $1.UpperBound ) );
}
;
ArrayDecl2:
'[' ']'
{
/**
** we identify a conformant array by setting the upperbound to -1
** and the lower to 0
**/
$$.UpperBound = (expr_node *) -1;
$$.LowerBound = (expr_node *) 0;
}
| '[' '*' ']'
{
/**
** This is also taken to mean a conformant array, upper bound known
** only at runtime. The lower bound is 0
**/
$$.UpperBound = (expr_node *)-1;
$$.LowerBound = (expr_node *)0;
}
| '[' ConstantExpr ']'
{
/**
** this is the case of an array whose lower bound is 0
**/
$$.UpperBound = $2;
$$.LowerBound = (expr_node *)0;
}
| '[' ArrayBoundsPair ']'
{
if( ($2.LowerBound)->Evaluate() != 0 )
ParseError( ARRAY_BOUNDS_CONSTRUCT_BAD, (char *)NULL );
$$ = $2;
}
;
ArrayBoundsPair:
ConstantExpr DOTDOT ConstantExpr
{
/**
** the fact that the expected expression is not a constant is
** verified by the constantExpr production. All we have to do here is
** to pass the expression up.
**/
$$.LowerBound = $1;
$$.UpperBound = new expr_b_arithmetic( OP_PLUS,
$3,
GetConstant1() );
}
;
InternationalCharacterType:
KWISOLATIN1
{
$$ = KWISOLATIN1;
}
| KWPRIVATECHAR8
{
$$ = KWPRIVATECHAR8;
}
| KWISOMULTILINGUAL
{
$$ = KWISOMULTILINGUAL;
}
| KWPRIVATECHAR16
{
$$ = KWPRIVATECHAR16;
}
| KWISOUCS
{
$$ = KWISOUCS;
}
;
/********************************* MIDL attributes **********************/
OptionalAttrList:
AttrList
| /* Empty */
{
$$.MakeAttrList();
}
;
OptionalAttrListWithDefault:
AttrListWithDefault
| /* Empty */
{
$$.MakeAttrList();
}
;
AttrList:
AttrList AttrSet
{
// note that in all left-recursive productions like this we are
// relying on an implicit $$ = $1 operation
$$.Merge( $2 );
}
| AttrSet
;
AttrListWithDefault:
AttrListWithDefault AttrSetWithDefault
{
// note that in all left-recursive productions like this we are
// relying on an implicit $$ = $1 operation
$$.Merge( $2 );
}
| AttrSetWithDefault
;
AttrSet:
'[' Attributes ']'
{
$$ = $2;
}
;
AttrSetWithDefault:
'[' AttributesWithDefault ']'
{
$$ = $2;
}
;
Attributes:
Attributes ',' OneAttribute
{
$$.Merge( $3 );
}
| OneAttribute
;
AttributesWithDefault:
AttributesWithDefault ',' OneAttributeWithDefault
{
$$.Merge( $3 );
}
| OneAttributeWithDefault
;
OneAttribute:
InterfaceAttribute
{
$$.MakeAttrList( $1 );
}
| TypeAttribute
{
$$.MakeAttrList( $1 );
}
| FieldAttribute
| PtrAttr
{
$$.MakeAttrList( $1 );
}
| DirectionalAttribute
{
$$.MakeAttrList( $1 );
}
| OperationAttribute
{
$$.MakeAttrList( $1 );
}
| OdlAttribute
{
$$.MakeAttrList( $1 );
}
;
OneAttributeWithDefault:
InterfaceAttribute
{
$$.MakeAttrList( $1 );
}
| TypeAttribute
{
$$.MakeAttrList( $1 );
}
| FieldAttribute
| PtrAttr
{
$$.MakeAttrList( $1 );
}
| DirectionalAttribute
{
$$.MakeAttrList( $1 );
}
| OperationAttribute
{
$$.MakeAttrList( $1 );
}
| OdlAttribute
{
$$.MakeAttrList( $1 );
}
| KWDEFAULT
{
$$.MakeAttrList(new battr( ATTR_DEFAULT ));
}
;
;
InterfaceAttribute:
KWENDPOINT '(' EndPtSpecs ')'
{
$$ = $3;
}
| KWUUID '('
{
LexContext = LEX_GUID; /* turned off by the lexer */
}
Guid ')'
{
$$ = $4;
}
| KWLOCAL
{
$$ = new battr( ATTR_LOCAL );
}
| KWOBJECT
{
ParseError( INVALID_OSF_ATTRIBUTE, "[object]" );
$$ = new battr( ATTR_OBJECT );
}
| KWVERSION '('
{
LexContext = LEX_VERSION;
/* LexContext is reset by lexer */
}
VERSIONTOKEN ')'
{
$$ = (new node_version( $4 ));
}
| KWDEFAULTPOINTER '(' PtrAttr ')'
{
$$ = $3;
}
| AcfInterfaceAttribute
{
if( !pCommand->IsSwitchDefined( SWITCH_APP_CONFIG ) )
{
ParseError( ACF_IN_IDL_NEEDS_APP_CONFIG,
($1)->GetNodeNameString() );
}
$$ = $1;
}
| /* empty attribute */
{
$$ = NULL;
}
;
Guid:
UUIDTOKEN
{
$$ = (new node_guid( $1 ));
}
;
EndPtSpecs:
EndPtSpec
{
$$ = new node_endpoint( $1 );
}
| EndPtSpecs ',' EndPtSpec
{
$$ = $1;
( (node_endpoint *) $$)->SetEndPointString( $3 );
}
;
EndPtSpec:
STRING
;
AcfInterfaceAttribute:
KWIMPLICITHANDLE '(' AcfImpHdlTypeSpec IDENTIFIER ')'
{
$$ = (new node_implicit( $3, new node_id_fe($4) ));
}
| KWAUTOHANDLE
{
$$ = (new acf_attr( ATTR_AUTO ));
}
;
AcfImpHdlTypeSpec:
KWHANDLET
{
GetBaseTypeNode( &($$), SIGN_UNDEF, SIZE_UNDEF, TYPE_HANDLE_T );
}
| IDENTIFIER
{
node_forward * pFwd;
SymKey SKey( $1, NAME_DEF );
pFwd = new node_forward( SKey, pCurSymTbl );
pFwd->SetSymName( $1 );
pFwd->SetAttribute( ATTR_HANDLE );
$$ = pFwd;
//
// keep a track of this node to ensure it is not used as a
// context handle.
//
if( ImportLevel == 0 )
{
pBaseImplicitHandle = $$;
}
}
| TypeName
;
TypeAttribute:
UnimplementedTypeAttribute
{
$$ = NULL;
}
| KWHANDLE
{
$$ = new battr( ATTR_HANDLE );
}
| KWSTRING
{
$$ = (new battr( ATTR_STRING ));
}
| KWBSTRING
{
$$ = (new battr( ATTR_BSTRING ));
}
| KWCONTEXTHANDLE
{
$$ = (new battr( ATTR_CONTEXT ));
}
| KWSWITCHTYPE '(' SwitchTypeSpec ')'
{
$$ = (new node_switch_type( $3 ));
}
| KWTRANSMITAS '(' SimpleTypeSpec ')'
{
$$ = (new node_transmit( $3 ));
}
| KWWIREMARSHAL '(' SimpleTypeSpec ')'
{
$$ = (new node_wire_marshal( $3 ));
}
| KWCALLAS '(' AcfCallType ')'
{
$$ = $3;
}
| KWMSUNION
{
$$ = new battr( ATTR_MS_UNION );
}
| KWOPAQUE
{
$$ = new battr( ATTR_OPAQUE );
}
| KWV1ENUM
{
$$ = new battr( ATTR_V1_ENUM );
}
;
AcfCallType:
IDENTIFIER
{
SymKey SKey( $1, NAME_PROC );
node_proc * pProc = (node_proc *)
pInterfaceInfoDict->GetInterfaceProcTable()->SymSearch( SKey );
$$ = new node_call_as( $1, pProc );
}
;
UnimplementedTypeAttribute:
KWALIGN '(' IntSize ')'
{
ParseError(IGNORE_UNIMPLEMENTED_ATTRIBUTE, "[align]");
}
| KWUNALIGNED
{
ParseError(IGNORE_UNIMPLEMENTED_ATTRIBUTE, "[unaligned]");
}
| KWV1ARRAY
{
ParseError(IGNORE_UNIMPLEMENTED_ATTRIBUTE, "[v1_array]");
}
| KWV1STRING
{
ParseError(IGNORE_UNIMPLEMENTED_ATTRIBUTE, "[v1_string]");
}
| KWV1STRUCT
{
ParseError(IGNORE_UNIMPLEMENTED_ATTRIBUTE, "[v1_struct]");
}
;
PtrAttr:
KWREF
{
$$ = new node_ptr_attr( PTR_REF );
}
| KWUNIQUE
{
$$ = new node_ptr_attr( PTR_UNIQUE );
}
| KWPTR
{
$$ = new node_ptr_attr( PTR_FULL );
}
| KWIGNORE
{
$$ = new battr( ATTR_IGNORE );
}
;
SwitchTypeSpec:
IntSpec
{
if( $1.BaseType == TYPE_UNDEF )
$1.BaseType = TYPE_INT;
if( $1.TypeSign == SIGN_UNDEF )
$1.TypeSign = SIGN_SIGNED;
GetBaseTypeNode( &($$), $1.TypeSign, $1.TypeSize, $1.BaseType );
}
| CharSpecs
{
GetBaseTypeNode( &($$), $1.TypeSign, SIZE_CHAR, TYPE_INT );
}
| KWBYTE
{
GetBaseTypeNode( &($$), SIGN_UNDEF, SIZE_UNDEF, TYPE_BYTE );
}
| KWBOOLEAN
{
GetBaseTypeNode( &($$), SIGN_UNDEF, SIZE_UNDEF, TYPE_BOOLEAN );
}
| KWENUM Tag
{
SymKey SKey( $2, NAME_ENUM );
if( ! ($$ = pBaseSymTbl->SymSearch( SKey ) ) )
{
ParseError( UNDEFINED_SYMBOL, $2 );
$$ = new node_error;
}
}
| TypeName /* TYPENAME */
;
FieldAttribute:
KWFIRSTIS '(' AttrVarList ')'
{
$$ = (GenerateFieldAttribute( ATTR_FIRST, $3 ));
}
| KWLASTIS '(' AttrVarList ')'
{
$$ = (GenerateFieldAttribute( ATTR_LAST, $3 ));
}
| KWLENGTHIS '(' AttrVarList ')'
{
$$ = (GenerateFieldAttribute( ATTR_LENGTH, $3 ));
}
| KWMINIS '(' AttrVarList ')'
{
$$ = (GenerateFieldAttribute( ATTR_MIN, $3 ));
}
| KWMAXIS '(' AttrVarList ')'
{
$$ = (GenerateFieldAttribute( ATTR_MAX, $3 ));
}
| KWSIZEIS '(' AttrVarList ')'
{
$$ = (GenerateFieldAttribute( ATTR_SIZE, $3 ));
}
| KWSWITCHIS '(' AttrVar ')'
{
$$.MakeAttrList( new node_switch_is( $3 ));
}
| KWIIDIS '(' AttrVar ')'
{
ParseError( INVALID_OSF_ATTRIBUTE, "[iid_is()]" );
$$.MakeAttrList( new size_attr( $3, ATTR_IID_IS ));
}
| KWID '(' ConstantExpr ')'
{
$$.MakeAttrList( new node_constant_attr( $3, ATTR_ID));
}
| KWHC '(' ConstantExpr ')'
{
$$.MakeAttrList( new node_constant_attr( $3, ATTR_HELPCONTEXT ));
}
| KWHSC '(' ConstantExpr ')'
{
if (!FNewTypeLib())
{
ParseError( INVALID_NEWTLB_ATTRIBUTE, "[helpstringcontext()]");
}
$$.MakeAttrList( new node_constant_attr( $3, ATTR_HELPSTRINGCONTEXT ));
}
| KWLCID '(' ConstantExpr ')'
{
$$.MakeAttrList( new node_constant_attr( $3, ATTR_LCID ));
}
| KWFUNCDESCATTR '(' ConstantExpr ')'
{
$$.MakeAttrList( new node_constant_attr( $3, ATTR_FUNCDESCATTR ));
}
| KWIDLDESCATTR '(' ConstantExpr ')'
{
$$.MakeAttrList( new node_constant_attr( $3, ATTR_IDLDESCATTR ));
}
| KWTYPEDESCATTR '(' ConstantExpr ')'
{
$$.MakeAttrList( new node_constant_attr( $3, ATTR_TYPEDESCATTR ));
}
| KWVARDESCATTR '(' ConstantExpr ')'
{
$$.MakeAttrList( new node_constant_attr( $3, ATTR_VARDESCATTR ));
}
| KWDLLNAME '(' STRING ')'
{
$$.MakeAttrList( new node_text_attr( $3, ATTR_DLLNAME ));
}
| KWHELPSTR '(' STRING ')'
{
TranslateEscapeSequences($3);
$$.MakeAttrList( new node_text_attr( $3, ATTR_HELPSTRING ));
}
| KWHELPFILE '(' STRING ')'
{
TranslateEscapeSequences($3);
$$.MakeAttrList( new node_text_attr( $3, ATTR_HELPFILE ));
}
| KWENTRY '(' STRING ')'
{
$$.MakeAttrList( new node_entry_attr( $3 ));
}
| KWENTRY '(' NUMERICCONSTANT ')'
{
$$.MakeAttrList( new node_entry_attr( (long) $3.Val ));
}
| KWENTRY '(' HEXCONSTANT ')'
{
$$.MakeAttrList( new node_entry_attr( (long) $3.Val ));
}
| KWENTRY '(' OCTALCONSTANT ')'
{
$$.MakeAttrList( new node_entry_attr( (long) $3.Val ));
}
| KWDEFAULTVALUE '(' ConstantExpr ')'
{
if (!FNewTypeLib())
{
ParseError( INVALID_NEWTLB_ATTRIBUTE, "[defaultvalue()]");
}
$$.MakeAttrList( new node_constant_attr( $3, ATTR_DEFAULTVALUE ));
}
| KWCUSTOM '('
{
LexContext = LEX_GUID; /* turned off by the lexer */
}
Guid ',' ConstantExpr ')'
{
if (!FNewTypeLib())
{
ParseError( INVALID_NEWTLB_ATTRIBUTE, "[custom()]");
}
$$.MakeAttrList( new node_custom_attr( (node_guid *)$4, $6 ));
}
;
AttrVarList:
AttrVarList ',' AttrVar
{
$$->SetPeer( $3 );
}
| AttrVar
{
$$ = new expr_list;
$$->SetPeer( $1 );
}
;
AttrVar:
VariableExpr
| /* empty */
{
$$ = NULL;
}
;
DirectionalAttribute:
KWIN OptShape
{
$$ = new battr ( ATTR_IN );
/*****************
if( $2 )
$$.Merge( ATTRLIST Shape_Attr($2) );
******************/
}
| KWOUT OptShape
{
$$ = new battr ( ATTR_OUT );
/*****************
if( $2 )
$$.Merge( ATTRLIST Shape_Attr($2) );
******************/
}
;
OperationAttribute:
KWCALLBACK
{
$$ = (new battr( ATTR_CALLBACK ));
}
| KWIDEMPOTENT
{
$$ = (new battr( ATTR_IDEMPOTENT ));
}
| KWBROADCAST
{
$$ = (new battr( ATTR_BROADCAST ));
}
| KWMAYBE
{
$$ = (new battr( ATTR_MAYBE ));
}
| KWASYNC
{
$$ = (new battr( ATTR_ASYNC ));
}
| KWINPUTSYNC
{
$$ = (new battr( ATTR_INPUTSYNC ));
}
;
OdlAttribute:
KWHIDDEN
{
$$ = (new battr( ATTR_HIDDEN ));
}
| KWPROPGET
{
$$ = (new node_member_attr( MATTR_PROPGET ));
}
| KWPROPPUT
{
$$ = (new node_member_attr( MATTR_PROPPUT ));
}
| KWPROPPUTREF
{
$$ = (new node_member_attr( MATTR_PROPPUTREF ));
}
| KWOPTIONAL
{
$$ = (new node_member_attr( MATTR_OPTIONAL ));
}
| KWVARARG
{
$$ = (new node_member_attr( MATTR_VARARG ));
}
| KWRESTRICTED
{
$$ = (new node_member_attr( MATTR_RESTRICTED ));
}
| KWREADONLY
{
$$ = (new node_member_attr( MATTR_READONLY ));
}
| KWSOURCE
{
$$ = (new node_member_attr( MATTR_SOURCE ));
}
| KWDEFAULTVTABLE
{
if (!FNewTypeLib())
{
ParseError( INVALID_NEWTLB_ATTRIBUTE, "[defaultvtable]");
}
$$ = (new node_member_attr( MATTR_DEFAULTVTABLE ));
}
| KWIMMEDIATEBIND
{
if (!FNewTypeLib())
{
ParseError( INVALID_NEWTLB_ATTRIBUTE, "[immediatebind]");
}
$$ = (new node_member_attr( MATTR_IMMEDIATEBIND ));
}
| KWREPLACEABLE
{
if (!FNewTypeLib())
{
ParseError( INVALID_NEWTLB_ATTRIBUTE, "[replaceable]");
}
$$ = (new node_member_attr( MATTR_REPLACEABLE ));
}
| KWUSESGETLASTERROR
{
$$ = (new node_member_attr( MATTR_USESGETLASTERROR ));
}
| KWBINDABLE
{
$$ = (new node_member_attr( MATTR_BINDABLE ));
}
| KWREQUESTEDIT
{
$$ = (new node_member_attr( MATTR_REQUESTEDIT ));
}
| KWDISPLAYBIND
{
$$ = (new node_member_attr( MATTR_DISPLAYBIND ));
}
| KWDEFAULTBIND
{
$$ = (new node_member_attr( MATTR_DEFAULTBIND ));
}
| KWPREDECLID
{
$$ = (new node_member_attr( MATTR_PREDECLID ));
}
| KWRETVAL
{
$$ = (new node_member_attr( MATTR_RETVAL ));
}
| KWAPPOBJECT
{
$$ = (new node_type_attr( TATTR_APPOBJECT ));
}
| KWPUBLIC
{
$$ = (new node_type_attr( TATTR_PUBLIC ));
}
| KWODL
{
$$ = NULL;
}
| KWLICENSED
{
$$ = (new node_type_attr( TATTR_LICENSED ));
}
| KWCONTROL
{
$$ = (new node_type_attr( TATTR_CONTROL ));
}
| KWDUAL
{
$$ = (new node_type_attr( TATTR_DUAL ));
}
| KWNONEXTENSIBLE
{
$$ = (new node_type_attr( TATTR_NONEXTENSIBLE ));
}
| KWOLEAUTOMATION
{
$$ = (new node_type_attr( TATTR_OLEAUTOMATION ));
}
| KWLCID
{
$$ = (new battr( ATTR_FLCID ));
}
| KWNONCREATABLE
{
if (!FNewTypeLib())
{
ParseError( INVALID_NEWTLB_ATTRIBUTE, "[noncreatable]");
}
$$ = (new node_type_attr( TATTR_NONCREATABLE ));
}
| KWAGGREGATABLE
{
if (!FNewTypeLib())
{
ParseError( INVALID_NEWTLB_ATTRIBUTE, "[aggregatable]");
}
$$ = (new node_type_attr( TATTR_AGGREGATABLE ));
}
| KWUIDEFAULT
{
if (!FNewTypeLib())
{
ParseError( INVALID_NEWTLB_ATTRIBUTE, "[uidefault]");
}
$$ = (new node_member_attr( MATTR_UIDEFAULT ));
}
| KWNONBROWSABLE
{
if (!FNewTypeLib())
{
ParseError( INVALID_NEWTLB_ATTRIBUTE, "[nonbrowsable]");
}
$$ = (new node_member_attr( MATTR_NONBROWSABLE ));
}
| KWDEFAULTCOLLELEM
{
if (!FNewTypeLib())
{
ParseError( INVALID_NEWTLB_ATTRIBUTE, "[defaultcollem]");
}
$$ = (new node_member_attr( MATTR_DEFAULTCOLLELEM ));
}
;
OptShape:
'(' KWSHAPE ')'
{
ParseError(IGNORE_UNIMPLEMENTED_ATTRIBUTE, "[shape]");
$$ = ATTR_NONE;
}
| /* Empty */
{
$$ = ATTR_NONE;
}
;
/*************** DANGER: EXPRESSIONS FOLLOW: ***************/
Initializer:
AssignmentExpr
{
$$ = $1;
#ifdef gajdebug3
printf("\t...init list has constant=%d, from %d\n",
$$->IsConstant(),$1->IsConstant() );
#endif
}
| '{' InitializerList OptionalComma '}'
{
ParseError( COMPOUND_INITS_NOT_SUPPORTED, (char *)0 );
$$ = NULL;
// $$ = new expr_init_list( (expr_node *)NULL );
// $$->LinkChild( $2 );
}
/**
** known bug : we need to figure out a way to simulate this hanging list
** maybe by creating a special expr_list node, such that it meets
** all semantic requirements also
**/
;
OptionalComma:
','
{
}
| /** Empty **/
{
}
;
InitializerList:
Initializer
{
// $$ = $1;
}
| InitializerList ',' Initializer
{
// $$->LinkSibling( $3 );
}
;
/***
*** VibhasC:WHERE IS THE production expr ',' AssignmentExpr valid ?
***/
Expr:
AssignmentExpr
| Expr ',' AssignmentExpr
{
$$ = $3;
}
;
VariableExpr:
ConditionalExpr
;
ConstantExpr:
ConditionalExpr
{
/**
** The expression must be a constant, if not report error
**/
#ifdef gajdebug3
printf("constant expr is: %d\n",$1->IsConstant());
#endif
if( ! $1->IsConstant() )
ParseError( EXPR_NOT_CONSTANT, (char *)NULL );
$$ = $1;
}
;
AssignmentExpr:
ConditionalExpr
| UnaryExpr AssignOps AssignmentExpr
{
/**
** we do not permit assignment in expressions
**/
ParseError( SYNTAX_ERROR, (char *)NULL );
$$ = new expr_error;
}
;
ConditionalExpr:
LogicalOrExpr
{
$$ = $1;
#if 0
printf("\n************** expression dump start ***************\n");
BufferManager * pOutput = new BufferManager( 10 );
$$->PrintExpr( (BufferManager *)NULL, (BufferManager *)NULL, pOutput );
pOutput->Print( stdout );
printf("\n****************************************************\n");
#endif // 0
}
| LogicalOrExpr '?' Expr ':' ConditionalExpr
{
/**
** This is a ternary operator.
**/
$$ = new expr_ternary( OP_QM, $1, $3, $5 );
}
;
LogicalOrExpr:
LogicalAndExpr
| LogicalOrExpr OROR LogicalAndExpr
{
$$ = new expr_b_logical( OP_LOGICAL_OR, $1, $3 );
}
;
LogicalAndExpr:
InclusiveOrExpr
| LogicalAndExpr ANDAND InclusiveOrExpr
{
$$ = new expr_b_logical( OP_LOGICAL_AND, $1, $3 );
}
;
InclusiveOrExpr:
ExclusiveOrExpr
| InclusiveOrExpr '|' ExclusiveOrExpr
{
$$ = new expr_bitwise( OP_OR, $1, $3 );
}
;
ExclusiveOrExpr:
AndExpr
| ExclusiveOrExpr '^' AndExpr
{
$$ = new expr_bitwise( OP_XOR, $1, $3 );
}
;
AndExpr:
EqualityExpr
| AndExpr '&' EqualityExpr
{
$$ = new expr_bitwise( OP_AND, $1, $3 );
}
;
EqualityExpr:
RelationalExpr
| EqualityExpr EQUALS RelationalExpr
{
$$ = new expr_relational( OP_EQUAL, $1, $3 );
}
| EqualityExpr NOTEQ RelationalExpr
{
$$ = new expr_relational( OP_NOT_EQUAL, $1, $3 );
}
;
RelationalExpr:
ShiftExpr
| RelationalExpr '<' ShiftExpr
{
$$ = new expr_relational( OP_LESS, $1, $3 );
}
| RelationalExpr '>' ShiftExpr
{
$$ = new expr_relational( OP_GREATER, $1, $3 );
}
| RelationalExpr LTEQ ShiftExpr
{
$$ = new expr_relational( OP_LESS_EQUAL, $1, $3 );
}
| RelationalExpr GTEQ ShiftExpr
{
$$ = new expr_relational( OP_GREATER_EQUAL, $1, $3 );
}
;
ShiftExpr:
AdditiveExpr
| ShiftExpr LSHIFT AdditiveExpr
{
$$ = new expr_shift( OP_LEFT_SHIFT, $1, $3 );
}
| ShiftExpr RSHIFT AdditiveExpr
{
$$ = new expr_shift( OP_RIGHT_SHIFT, $1, $3 );
}
;
AdditiveExpr:
MultExpr
| AdditiveExpr AddOp MultExpr
{
$$ = new expr_b_arithmetic( $2, $1, $3 );
}
;
MultExpr:
CastExpr
| MultExpr MultOp CastExpr
{
$$ = new expr_b_arithmetic( $2, $1, $3 );
}
;
CastExpr:
UnaryExpr
| '(' DeclarationSpecifiers OptionalDeclarator ')' CastExpr
{
node_skl * pNode = pErrorTypeNode;
if( $2.pNode )
{
if( $3.pHighest )
{
$3.pLowest->SetChild( $2.pNode );
pNode = $3.pHighest;
if( $2.modifiers )
{
( (named_node *) $3.pLowest)->SetModifiers( $2.modifiers );
}
}
else
pNode = $2.pNode;
}
$$ = new expr_cast( pNode, $5 );
}
;
UnaryExpr:
PostfixExpr
| UnaryOp CastExpr
{
( (expr_op_unary *) ($$ = $1) )->SetLeft( $2 );
if ( $2 )
( (expr_op_unary *) $$)->SetConstant( $2->IsConstant() );
}
| KWSIZEOF '(' DeclarationSpecifiers OptionalDeclarator ')'
{
/**
** The sizeof construct looks like a declaration and a possible
** declarator. All we really do, is to contruct the type ( graph )
** and hand it over to the sizeof expression node. If there was an
** error, just construct the size of with an error node
**/
node_skl * pNode = pErrorTypeNode;
node_skl * pLow;
if( $3.pNode )
{
if( $4.pHighest )
{
pNode = $4.pHighest;
pLow = $4.pLowest;
pLow->SetChild( $3.pNode );
pLow->SetModifiers( $3.modifiers );
}
else
{
pNode = $3.pNode;
}
}
$$ = new expr_sizeof( pNode );
}
| KWSIZEOF UnaryExpr
{
$$ = new expr_sizeof( $2 );
}
;
PostfixExpr:
PrimaryExpr
| PostfixExpr '[' Expr ']'
{
$$ = new expr_index( $1, $3 );
}
| PostfixExpr '(' ArgExprList ')'
{
/**
** not implemented
**/
ParseError( EXPR_NOT_IMPLEMENTED, (char *)NULL );
$$ = new expr_error;
}
| PostfixExpr POINTSTO IDENTIFIER
{
expr_variable * pIDExpr = new expr_variable( $3 );
$$ = new expr_pointsto( $1, pIDExpr );
}
| PostfixExpr '.' IDENTIFIER
{
expr_variable * pIDExpr = new expr_variable( $3 );
$$ = new expr_dot( $1, pIDExpr );
}
;
PrimaryExpr:
IDENTIFIER
{
// true if the identifier represents a constant
BOOL ConstVar = FALSE;
named_node * pNode = NULL;
SymKey SKey( $1, NAME_MEMBER );
pNode = pCurSymTbl->SymSearch( SKey );
// look for a global ID matching the id
if ( ! pNode )
{
SymKey SKey2( $1, NAME_ID );
pNode = pBaseSymTbl->SymSearch( SKey2 );
ConstVar = (pNode) ? ((node_id_fe *) pNode)->IsConstant() : FALSE;
}
// look for a global enum label matching the id
if ( !pNode )
{
SymKey SKey2( $1, NAME_LABEL );
pNode = pBaseSymTbl->SymSearch( SKey2 );
ConstVar = (pNode != NULL);
}
if ( !pNode ) pNode = new node_forward( SKey, pCurSymTbl );
if (ConstVar)
{
$$ = new expr_named_constant( $1, pNode );
}
else
{
$$ = new expr_variable( $1, pNode );
}
}
| NUMERICCONSTANT
{
$$ = new expr_constant( (long) $1.Val, VALUE_TYPE_NUMERIC );
}
| NUMERICUCONSTANT
{
$$ = new expr_constant( (long) $1.Val, VALUE_TYPE_NUMERIC_U);
node_skl * pType;
GetBaseTypeNode( &pType, SIGN_UNSIGNED,SIZE_UNDEF,TYPE_INT );
$$->SetType( pType );
}
| NUMERICLONGCONSTANT
{
$$ = new expr_constant( (long) $1.Val, VALUE_TYPE_NUMERIC_LONG);
node_skl * pType;
GetBaseTypeNode( &pType, SIGN_SIGNED,SIZE_LONG,TYPE_INT );
$$->SetType( pType );
}
| NUMERICULONGCONSTANT
{
$$ = new expr_constant( (long) $1.Val, VALUE_TYPE_NUMERIC_ULONG);
node_skl * pType;
GetBaseTypeNode( &pType, SIGN_UNSIGNED,SIZE_LONG,TYPE_INT );
$$->SetType( pType );
}
| HEXCONSTANT
{
$$ = new expr_constant( (long) $1.Val, VALUE_TYPE_HEX );
}
| HEXUCONSTANT
{
$$ = new expr_constant( (long) $1.Val, VALUE_TYPE_HEX_U);
node_skl * pType;
GetBaseTypeNode( &pType, SIGN_UNSIGNED,SIZE_UNDEF,TYPE_INT );
$$->SetType( pType );
}
| HEXLONGCONSTANT
{
$$ = new expr_constant( (long) $1.Val, VALUE_TYPE_HEX_LONG);
node_skl * pType;
GetBaseTypeNode( &pType, SIGN_SIGNED,SIZE_LONG,TYPE_INT );
$$->SetType( pType );
}
| HEXULONGCONSTANT
{
$$ = new expr_constant( (long) $1.Val, VALUE_TYPE_HEX_ULONG);
node_skl * pType;
GetBaseTypeNode( &pType, SIGN_UNSIGNED,SIZE_LONG,TYPE_INT );
$$->SetType( pType );
}
| OCTALCONSTANT
{
$$ = new expr_constant( (long) $1.Val, VALUE_TYPE_OCTAL );
}
| OCTALUCONSTANT
{
$$ = new expr_constant( (long) $1.Val, VALUE_TYPE_OCTAL_U);
node_skl * pType;
GetBaseTypeNode( &pType, SIGN_UNSIGNED,SIZE_UNDEF,TYPE_INT );
$$->SetType( pType );
}
| OCTALLONGCONSTANT
{
$$ = new expr_constant( (long) $1.Val, VALUE_TYPE_OCTAL_LONG);
node_skl * pType;
GetBaseTypeNode( &pType, SIGN_SIGNED,SIZE_LONG,TYPE_INT );
$$->SetType( pType );
}
| OCTALULONGCONSTANT
{
$$ = new expr_constant( (long) $1.Val, VALUE_TYPE_OCTAL_ULONG);
node_skl * pType;
GetBaseTypeNode( &pType, SIGN_UNSIGNED,SIZE_LONG,TYPE_INT );
$$->SetType( pType );
}
| TOKENTRUE
{
$$ = new expr_constant( (long)TRUE, VALUE_TYPE_BOOL );
}
| TOKENFALSE
{
$$ = new expr_constant( (long)FALSE, VALUE_TYPE_BOOL );
}
| KWTOKENNULL
{
$$ = new expr_constant( (char *)NULL, VALUE_TYPE_STRING );
}
| STRING
{
$$ = new expr_constant( (char *)$1, VALUE_TYPE_STRING );
}
| WIDECHARACTERSTRING
{
ParseError( WCHAR_STRING_NOT_OSF, (char *)NULL );
$$ = new expr_constant( (wchar_t *)$1, VALUE_TYPE_WSTRING );
}
| CHARACTERCONSTANT
{
$$ = new expr_constant( (long)( ((long)$1.Val) & 0xff ) ,
VALUE_TYPE_CHAR );
}
| WIDECHARACTERCONSTANT
{
$$ = new expr_constant( (long)( ((long)$1.Val ) & 0xffff ),
VALUE_TYPE_WCHAR );
ParseError( WCHAR_CONSTANT_NOT_OSF, (char *)NULL );
}
| '(' Expr ')'
{
$$ = $2;
}
;
UnaryOp:
AddOp
{
$$ = new expr_u_arithmetic( ($1 == OP_PLUS) ?
OP_UNARY_PLUS : OP_UNARY_MINUS,
NULL );
}
| '!'
{
$$ = new expr_u_not( NULL );
}
| '&'
{
$$ = new expr_u_deref( OP_UNARY_AND, NULL );
}
| '*'
{
$$ = new expr_u_deref( OP_UNARY_INDIRECTION, NULL );
}
| '~'
{
$$ = new expr_u_complement( NULL);
}
;
AddOp:
'+'
{
$$ = OP_PLUS;
}
| '-'
{
$$ = OP_MINUS;
}
;
MultOp:
'*'
{
$$ = OP_STAR;
}
| '/'
{
$$ = OP_SLASH;
}
| '%'
{
$$ = OP_MOD;
}
;
ArgExprList:
AssignmentExpr
{
ParseError( EXPR_NOT_IMPLEMENTED, (char *)NULL );
$$ = new expr_error;
}
| ArgExprList ',' AssignmentExpr
{
/* UNIMPLEMENTED YET */
$$ = $1;
}
;
AssignOps:
MULASSIGN
| DIVASSIGN
| MODASSIGN
| ADDASSIGN
| SUBASSIGN
| LEFTASSIGN
| RIGHTASSIGN
| ANDASSIGN
| XORASSIGN
| ORASSIGN
;
%%
/***************************************************************************
* utility routines
**************************************************************************/
YYSTATIC VOID FARCODE PASCAL
yyerror(char *szError)
{
// this routine should really never be called now, since I
// modified yypars.c to report errors thru the ParseError
// mechanism
fprintf(stderr, szError);
}
void
NTDBG( char * p )
{
printf("VC_DBG: %s\n", p );
}