diff options
Diffstat (limited to 'src/ilasm/asmparse.y')
-rw-r--r-- | src/ilasm/asmparse.y | 2053 |
1 files changed, 2053 insertions, 0 deletions
diff --git a/src/ilasm/asmparse.y b/src/ilasm/asmparse.y new file mode 100644 index 0000000000..051df92199 --- /dev/null +++ b/src/ilasm/asmparse.y @@ -0,0 +1,2053 @@ +%{ + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// File asmparse.y +// +#include "ilasmpch.h" + +#include "grammar_before.cpp" + +%} + +%union { + CorRegTypeAttr classAttr; + CorMethodAttr methAttr; + CorFieldAttr fieldAttr; + CorMethodImpl implAttr; + CorEventAttr eventAttr; + CorPropertyAttr propAttr; + CorPinvokeMap pinvAttr; + CorDeclSecurity secAct; + CorFileFlags fileAttr; + CorAssemblyFlags asmAttr; + CorAssemblyFlags asmRefAttr; + CorTypeAttr exptAttr; + CorManifestResourceFlags manresAttr; + double* float64; + __int64* int64; + __int32 int32; + char* string; + BinStr* binstr; + Labels* labels; + Instr* instr; // instruction opcode + NVPair* pair; + pTyParList typarlist; + mdToken token; + TypeDefDescr* tdd; + CustomDescr* cad; + unsigned short opcode; +}; + + /* These are returned by the LEXER and have values */ +%token ERROR_ BAD_COMMENT_ BAD_LITERAL_ /* bad strings, */ +%token <string> ID /* testing343 */ +%token <string> DOTTEDNAME /* System.Object */ +%token <binstr> QSTRING /* "Hello World\n" */ +%token <string> SQSTRING /* 'Hello World\n' */ +%token <int32> INT32 /* 3425 0x34FA 0352 */ +%token <int64> INT64 /* 342534523534534 0x34FA434644554 */ +%token <float64> FLOAT64 /* -334234 24E-34 */ +%token <int32> HEXBYTE /* 05 1A FA */ +%token <tdd> TYPEDEF_T +%token <tdd> TYPEDEF_M +%token <tdd> TYPEDEF_F +%token <tdd> TYPEDEF_TS +%token <tdd> TYPEDEF_MR +%token <tdd> TYPEDEF_CA + + + /* multi-character punctuation */ +%token DCOLON /* :: */ +%token ELIPSIS /* ... */ + + /* Keywords Note the undersores are to avoid collisions as these are common names */ +%token VOID_ BOOL_ CHAR_ UNSIGNED_ INT_ INT8_ INT16_ INT32_ INT64_ FLOAT_ FLOAT32_ FLOAT64_ BYTEARRAY_ +%token UINT_ UINT8_ UINT16_ UINT32_ UINT64_ FLAGS_ CALLCONV_ MDTOKEN_ +%token OBJECT_ STRING_ NULLREF_ + /* misc keywords */ +%token DEFAULT_ CDECL_ VARARG_ STDCALL_ THISCALL_ FASTCALL_ CLASS_ +%token TYPEDREF_ UNMANAGED_ FINALLY_ HANDLER_ CATCH_ FILTER_ FAULT_ +%token EXTENDS_ IMPLEMENTS_ TO_ AT_ TLS_ TRUE_ FALSE_ _INTERFACEIMPL + + /* class, method, field attributes */ + +%token VALUE_ VALUETYPE_ NATIVE_ INSTANCE_ SPECIALNAME_ FORWARDER_ +%token STATIC_ PUBLIC_ PRIVATE_ FAMILY_ FINAL_ SYNCHRONIZED_ INTERFACE_ SEALED_ NESTED_ +%token ABSTRACT_ AUTO_ SEQUENTIAL_ EXPLICIT_ ANSI_ UNICODE_ AUTOCHAR_ IMPORT_ ENUM_ +%token VIRTUAL_ NOINLINING_ AGGRESSIVEINLINING_ NOOPTIMIZATION_ UNMANAGEDEXP_ BEFOREFIELDINIT_ +%token STRICT_ RETARGETABLE_ WINDOWSRUNTIME_ NOPLATFORM_ +%token METHOD_ FIELD_ PINNED_ MODREQ_ MODOPT_ SERIALIZABLE_ PROPERTY_ TYPE_ +%token ASSEMBLY_ FAMANDASSEM_ FAMORASSEM_ PRIVATESCOPE_ HIDEBYSIG_ NEWSLOT_ RTSPECIALNAME_ PINVOKEIMPL_ +%token _CTOR _CCTOR LITERAL_ NOTSERIALIZED_ INITONLY_ REQSECOBJ_ + /* method implementation attributes: NATIVE_ and UNMANAGED_ listed above */ +%token CIL_ OPTIL_ MANAGED_ FORWARDREF_ PRESERVESIG_ RUNTIME_ INTERNALCALL_ + /* PInvoke-specific keywords */ +%token _IMPORT NOMANGLE_ LASTERR_ WINAPI_ AS_ BESTFIT_ ON_ OFF_ CHARMAPERROR_ + + /* intruction tokens (actually instruction groupings) */ +%token <opcode> INSTR_NONE INSTR_VAR INSTR_I INSTR_I8 INSTR_R INSTR_BRTARGET INSTR_METHOD INSTR_FIELD +%token <opcode> INSTR_TYPE INSTR_STRING INSTR_SIG INSTR_TOK +%token <opcode> INSTR_SWITCH + + /* assember directives */ +%token _CLASS _NAMESPACE _METHOD _FIELD _DATA _THIS _BASE _NESTER +%token _EMITBYTE _TRY _MAXSTACK _LOCALS _ENTRYPOINT _ZEROINIT +%token _EVENT _ADDON _REMOVEON _FIRE _OTHER +%token _PROPERTY _SET _GET DEFAULT_ +%token _PERMISSION _PERMISSIONSET + + /* security actions */ +%token REQUEST_ DEMAND_ ASSERT_ DENY_ PERMITONLY_ LINKCHECK_ INHERITCHECK_ +%token REQMIN_ REQOPT_ REQREFUSE_ PREJITGRANT_ PREJITDENY_ NONCASDEMAND_ +%token NONCASLINKDEMAND_ NONCASINHERITANCE_ + + /* extern debug info specifier (to be used by precompilers only) */ +%token _LINE P_LINE _LANGUAGE + /* custom value specifier */ +%token _CUSTOM + /* local vars zeroinit specifier */ +%token INIT_ + /* class layout */ +%token _SIZE _PACK +%token _VTABLE _VTFIXUP FROMUNMANAGED_ CALLMOSTDERIVED_ _VTENTRY RETAINAPPDOMAIN_ + /* manifest */ +%token _FILE NOMETADATA_ _HASH _ASSEMBLY _PUBLICKEY _PUBLICKEYTOKEN ALGORITHM_ _VER _LOCALE EXTERN_ +%token _MRESOURCE +%token _MODULE _EXPORT +%token LEGACY_ LIBRARY_ X86_ IA64_ AMD64_ ARM_ + /* field marshaling */ +%token MARSHAL_ CUSTOM_ SYSSTRING_ FIXED_ VARIANT_ CURRENCY_ SYSCHAR_ DECIMAL_ DATE_ BSTR_ TBSTR_ LPSTR_ +%token LPWSTR_ LPTSTR_ OBJECTREF_ IUNKNOWN_ IDISPATCH_ STRUCT_ SAFEARRAY_ BYVALSTR_ LPVOID_ ANY_ ARRAY_ LPSTRUCT_ +%token IIDPARAM_ + /* parameter attributes */ +%token IN_ OUT_ OPT_ PARAM_ + /* method implementations */ +%token _OVERRIDE WITH_ + /* variant type specifics */ +%token NULL_ ERROR_ HRESULT_ CARRAY_ USERDEFINED_ RECORD_ FILETIME_ BLOB_ STREAM_ STORAGE_ +%token STREAMED_OBJECT_ STORED_OBJECT_ BLOB_OBJECT_ CF_ CLSID_ VECTOR_ + /* header flags */ +%token _SUBSYSTEM _CORFLAGS ALIGNMENT_ _IMAGEBASE _STACKRESERVE + + /* syntactic sugar */ +%token _TYPEDEF _TEMPLATE _TYPELIST _MSCORLIB + + /* compilation control directives */ +%token P_DEFINE P_UNDEF P_IFDEF P_IFNDEF P_ELSE P_ENDIF P_INCLUDE + + /* nonTerminals */ +%type <string> dottedName id methodName atOpt slashedName +%type <labels> labels +%type <int32> callConv callKind int32 customHead customHeadWithOwner vtfixupAttr paramAttr ddItemCount variantType repeatOpt truefalse typarAttrib typarAttribs +%type <int32> iidParamIndex genArity genArityNotEmpty +%type <float64> float64 +%type <int64> int64 +%type <binstr> sigArgs0 sigArgs1 sigArg type bound bounds1 bytes hexbytes nativeType marshalBlob initOpt compQstring caValue +%type <binstr> marshalClause +%type <binstr> fieldInit serInit fieldSerInit +%type <binstr> f32seq f64seq i8seq i16seq i32seq i64seq boolSeq sqstringSeq classSeq objSeq +%type <binstr> simpleType +%type <binstr> tyArgs0 tyArgs1 tyArgs2 typeList typeListNotEmpty tyBound +%type <binstr> customBlobDescr serializType customBlobArgs customBlobNVPairs +%type <binstr> secAttrBlob secAttrSetBlob +%type <int32> fieldOrProp intOrWildcard +%type <typarlist> typarsRest typars typarsClause +%type <token> className typeSpec ownerType customType memberRef methodRef mdtoken +%type <classAttr> classAttr +%type <methAttr> methAttr +%type <fieldAttr> fieldAttr +%type <implAttr> implAttr +%type <eventAttr> eventAttr +%type <propAttr> propAttr +%type <pinvAttr> pinvAttr +%type <pair> nameValPairs nameValPair +%type <secAct> secAction +%type <secAct> psetHead +%type <fileAttr> fileAttr +%type <fileAttr> fileEntry +%type <asmAttr> asmAttr +%type <exptAttr> exptAttr +%type <manresAttr> manresAttr +%type <cad> customDescr customDescrWithOwner +%type <instr> instr_none instr_var instr_i instr_i8 instr_r instr_brtarget instr_method instr_field +%type <instr> instr_type instr_string instr_sig instr_tok instr_switch +%type <instr> instr_r_head + +%start decls + +/**************************************************************************/ +%% + +decls : /* EMPTY */ + | decls decl + ; +/* Module-level declarations */ +decl : classHead '{' classDecls '}' { PASM->EndClass(); } + | nameSpaceHead '{' decls '}' { PASM->EndNameSpace(); } + | methodHead methodDecls '}' { if(PASM->m_pCurMethod->m_ulLines[1] ==0) + { PASM->m_pCurMethod->m_ulLines[1] = PASM->m_ulCurLine; + PASM->m_pCurMethod->m_ulColumns[1]=PASM->m_ulCurColumn;} + PASM->EndMethod(); } + | fieldDecl + | dataDecl + | vtableDecl + | vtfixupDecl + | extSourceSpec + | fileDecl + | assemblyHead '{' assemblyDecls '}' { PASMM->EndAssembly(); } + | assemblyRefHead '{' assemblyRefDecls '}' { PASMM->EndAssembly(); } + | exptypeHead '{' exptypeDecls '}' { PASMM->EndComType(); } + | manifestResHead '{' manifestResDecls '}' { PASMM->EndManifestRes(); } + | moduleHead + | secDecl + | customAttrDecl + | _SUBSYSTEM int32 { +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:22011) // Suppress PREFast warning about integer overflow/underflow +#endif + PASM->m_dwSubsystem = $2; +#ifdef _PREFAST_ +#pragma warning(pop) +#endif + } + | _CORFLAGS int32 { PASM->m_dwComImageFlags = $2; } + | _FILE ALIGNMENT_ int32 { PASM->m_dwFileAlignment = $3; + if(($3 & ($3 - 1))||($3 < 0x200)||($3 > 0x10000)) + PASM->report->error("Invalid file alignment, must be power of 2 from 0x200 to 0x10000\n");} + | _IMAGEBASE int64 { PASM->m_stBaseAddress = (ULONGLONG)(*($2)); delete $2; + if(PASM->m_stBaseAddress & 0xFFFF) + PASM->report->error("Invalid image base, must be 0x10000-aligned\n");} + | _STACKRESERVE int64 { PASM->m_stSizeOfStackReserve = (size_t)(*($2)); delete $2; } + | languageDecl + | typedefDecl + | compControl + | _TYPELIST '{' classNameSeq '}' + | _MSCORLIB { PASM->m_fIsMscorlib = TRUE; } + ; + +classNameSeq : /* EMPTY */ + | className classNameSeq + ; + +compQstring : QSTRING { $$ = $1; } + | compQstring '+' QSTRING { $$ = $1; $$->append($3); delete $3; } + ; + +languageDecl : _LANGUAGE SQSTRING { LPCSTRToGuid($2,&(PASM->m_guidLang)); } + | _LANGUAGE SQSTRING ',' SQSTRING { LPCSTRToGuid($2,&(PASM->m_guidLang)); + LPCSTRToGuid($4,&(PASM->m_guidLangVendor));} + | _LANGUAGE SQSTRING ',' SQSTRING ',' SQSTRING { LPCSTRToGuid($2,&(PASM->m_guidLang)); + LPCSTRToGuid($4,&(PASM->m_guidLangVendor)); + LPCSTRToGuid($4,&(PASM->m_guidDoc));} + ; +/* Basic tokens */ +id : ID { $$ = $1; } + | SQSTRING { $$ = $1; } + ; + +dottedName : id { $$ = $1; } + | DOTTEDNAME { $$ = $1; } + | dottedName '.' dottedName { $$ = newStringWDel($1, '.', $3); } + ; + +int32 : INT32 { $$ = $1; } + ; + +int64 : INT64 { $$ = $1; } + | INT32 { $$ = neg ? new __int64($1) : new __int64((unsigned)$1); } + ; + +float64 : FLOAT64 { $$ = $1; } + | FLOAT32_ '(' int32 ')' { float f; *((__int32*) (&f)) = $3; $$ = new double(f); } + | FLOAT64_ '(' int64 ')' { $$ = (double*) $3; } + ; + +/* Aliasing of types, type specs, methods, fields and custom attributes */ +typedefDecl : _TYPEDEF type AS_ dottedName { PASM->AddTypeDef($2,$4); } + | _TYPEDEF className AS_ dottedName { PASM->AddTypeDef($2,$4); } + | _TYPEDEF memberRef AS_ dottedName { PASM->AddTypeDef($2,$4); } + | _TYPEDEF customDescr AS_ dottedName { $2->tkOwner = 0; PASM->AddTypeDef($2,$4); } + | _TYPEDEF customDescrWithOwner AS_ dottedName { PASM->AddTypeDef($2,$4); } + ; + +/* Compilation control directives are processed within yylex(), + displayed here just for grammar completeness */ +compControl : P_DEFINE dottedName { DefineVar($2, NULL); } + | P_DEFINE dottedName compQstring { DefineVar($2, $3); } + | P_UNDEF dottedName { UndefVar($2); } + | P_IFDEF dottedName { SkipToken = !IsVarDefined($2); + IfEndif++; + } + | P_IFNDEF dottedName { SkipToken = IsVarDefined($2); + IfEndif++; + } + | P_ELSE { if(IfEndif == 1) SkipToken = !SkipToken;} + | P_ENDIF { if(IfEndif == 0) + PASM->report->error("Unmatched #endif\n"); + else IfEndif--; + } + | P_INCLUDE QSTRING { _ASSERTE(!"yylex should have dealt with this"); } + | ';' { } + ; + +/* Custom attribute declarations */ +customDescr : _CUSTOM customType { $$ = new CustomDescr(PASM->m_tkCurrentCVOwner, $2, NULL); } + | _CUSTOM customType '=' compQstring { $$ = new CustomDescr(PASM->m_tkCurrentCVOwner, $2, $4); } + | _CUSTOM customType '=' '{' customBlobDescr '}' { $$ = new CustomDescr(PASM->m_tkCurrentCVOwner, $2, $5); } + | customHead bytes ')' { $$ = new CustomDescr(PASM->m_tkCurrentCVOwner, $1, $2); } + ; + +customDescrWithOwner : _CUSTOM '(' ownerType ')' customType { $$ = new CustomDescr($3, $5, NULL); } + | _CUSTOM '(' ownerType ')' customType '=' compQstring { $$ = new CustomDescr($3, $5, $7); } + | _CUSTOM '(' ownerType ')' customType '=' '{' customBlobDescr '}' + { $$ = new CustomDescr($3, $5, $8); } + | customHeadWithOwner bytes ')' { $$ = new CustomDescr(PASM->m_tkCurrentCVOwner, $1, $2); } + ; + +customHead : _CUSTOM customType '=' '(' { $$ = $2; bParsingByteArray = TRUE; } + ; + +customHeadWithOwner : _CUSTOM '(' ownerType ')' customType '=' '(' + { PASM->m_pCustomDescrList = NULL; + PASM->m_tkCurrentCVOwner = $3; + $$ = $5; bParsingByteArray = TRUE; } + ; + +customType : methodRef { $$ = $1; } + ; + +ownerType : typeSpec { $$ = $1; } + | memberRef { $$ = $1; } + ; + +/* Verbal description of custom attribute initialization blob */ +customBlobDescr : customBlobArgs customBlobNVPairs { $$ = $1; + $$->appendInt16(nCustomBlobNVPairs); + $$->append($2); + nCustomBlobNVPairs = 0; } + ; + +customBlobArgs : /* EMPTY */ { $$ = new BinStr(); $$->appendInt16(VAL16(0x0001)); } + | customBlobArgs serInit { $$ = $1; + $$->appendFrom($2, (*($2->ptr()) == ELEMENT_TYPE_SZARRAY) ? 2 : 1); } + | customBlobArgs compControl { $$ = $1; } + ; + +customBlobNVPairs : /* EMPTY */ { $$ = new BinStr(); } + | customBlobNVPairs fieldOrProp serializType dottedName '=' serInit + { $$ = $1; $$->appendInt8($2); + $$->append($3); + AppendStringWithLength($$,$4); + $$->appendFrom($6, (*($6->ptr()) == ELEMENT_TYPE_SZARRAY) ? 2 : 1); + nCustomBlobNVPairs++; } + | customBlobNVPairs compControl { $$ = $1; } + ; + +fieldOrProp : FIELD_ { $$ = SERIALIZATION_TYPE_FIELD; } + | PROPERTY_ { $$ = SERIALIZATION_TYPE_PROPERTY; } + ; + +customAttrDecl : customDescr { if($1->tkOwner && !$1->tkInterfacePair) + PASM->DefineCV($1); + else if(PASM->m_pCustomDescrList) + PASM->m_pCustomDescrList->PUSH($1); } + | customDescrWithOwner { PASM->DefineCV($1); } + | TYPEDEF_CA { CustomDescr* pNew = new CustomDescr($1->m_pCA); + if(pNew->tkOwner == 0) pNew->tkOwner = PASM->m_tkCurrentCVOwner; + if(pNew->tkOwner) + PASM->DefineCV(pNew); + else if(PASM->m_pCustomDescrList) + PASM->m_pCustomDescrList->PUSH(pNew); } + ; + +serializType : simpleType { $$ = $1; } + | TYPE_ { $$ = new BinStr(); $$->appendInt8(SERIALIZATION_TYPE_TYPE); } + | OBJECT_ { $$ = new BinStr(); $$->appendInt8(SERIALIZATION_TYPE_TAGGED_OBJECT); } + | ENUM_ CLASS_ SQSTRING { $$ = new BinStr(); $$->appendInt8(SERIALIZATION_TYPE_ENUM); + AppendStringWithLength($$,$3); } + | ENUM_ className { $$ = new BinStr(); $$->appendInt8(SERIALIZATION_TYPE_ENUM); + AppendStringWithLength($$,PASM->ReflectionNotation($2)); } + | serializType '[' ']' { $$ = $1; $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + ; + + +/* Module declaration */ +moduleHead : _MODULE { PASMM->SetModuleName(NULL); PASM->m_tkCurrentCVOwner=1; } + | _MODULE dottedName { PASMM->SetModuleName($2); PASM->m_tkCurrentCVOwner=1; } + | _MODULE EXTERN_ dottedName { BinStr* pbs = new BinStr(); + unsigned L = (unsigned)strlen($3); + memcpy((char*)(pbs->getBuff(L)),$3,L); + PASM->EmitImport(pbs); delete pbs;} + ; + +/* VTable Fixup table declaration */ +vtfixupDecl : _VTFIXUP '[' int32 ']' vtfixupAttr AT_ id { /*PASM->SetDataSection(); PASM->EmitDataLabel($7);*/ + PASM->m_VTFList.PUSH(new VTFEntry((USHORT)$3, (USHORT)$5, $7)); } + ; + +vtfixupAttr : /* EMPTY */ { $$ = 0; } + | vtfixupAttr INT32_ { $$ = $1 | COR_VTABLE_32BIT; } + | vtfixupAttr INT64_ { $$ = $1 | COR_VTABLE_64BIT; } + | vtfixupAttr FROMUNMANAGED_ { $$ = $1 | COR_VTABLE_FROM_UNMANAGED; } + | vtfixupAttr CALLMOSTDERIVED_ { $$ = $1 | COR_VTABLE_CALL_MOST_DERIVED; } + | vtfixupAttr RETAINAPPDOMAIN_ { $$ = $1 | COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN; } + ; + +vtableDecl : vtableHead bytes ')' /* deprecated */ { PASM->m_pVTable = $2; } + ; + +vtableHead : _VTABLE '=' '(' /* deprecated */ { bParsingByteArray = TRUE; } + ; + +/* Namespace and class declaration */ +nameSpaceHead : _NAMESPACE dottedName { PASM->StartNameSpace($2); } + ; + +_class : _CLASS { newclass = TRUE; } + ; + +classHeadBegin : _class classAttr dottedName typarsClause { if($4) FixupConstraints(); + PASM->StartClass($3, $2, $4); + TyParFixupList.RESET(false); + newclass = FALSE; + } + ; +classHead : classHeadBegin extendsClause implClause { PASM->AddClass(); } + ; + +classAttr : /* EMPTY */ { $$ = (CorRegTypeAttr) 0; } + | classAttr PUBLIC_ { $$ = (CorRegTypeAttr) (($1 & ~tdVisibilityMask) | tdPublic); } + | classAttr PRIVATE_ { $$ = (CorRegTypeAttr) (($1 & ~tdVisibilityMask) | tdNotPublic); } + | classAttr VALUE_ { $$ = (CorRegTypeAttr) ($1 | 0x80000000 | tdSealed); } + | classAttr ENUM_ { $$ = (CorRegTypeAttr) ($1 | 0x40000000); } + | classAttr INTERFACE_ { $$ = (CorRegTypeAttr) ($1 | tdInterface | tdAbstract); } + | classAttr SEALED_ { $$ = (CorRegTypeAttr) ($1 | tdSealed); } + | classAttr ABSTRACT_ { $$ = (CorRegTypeAttr) ($1 | tdAbstract); } + | classAttr AUTO_ { $$ = (CorRegTypeAttr) (($1 & ~tdLayoutMask) | tdAutoLayout); } + | classAttr SEQUENTIAL_ { $$ = (CorRegTypeAttr) (($1 & ~tdLayoutMask) | tdSequentialLayout); } + | classAttr EXPLICIT_ { $$ = (CorRegTypeAttr) (($1 & ~tdLayoutMask) | tdExplicitLayout); } + | classAttr ANSI_ { $$ = (CorRegTypeAttr) (($1 & ~tdStringFormatMask) | tdAnsiClass); } + | classAttr UNICODE_ { $$ = (CorRegTypeAttr) (($1 & ~tdStringFormatMask) | tdUnicodeClass); } + | classAttr AUTOCHAR_ { $$ = (CorRegTypeAttr) (($1 & ~tdStringFormatMask) | tdAutoClass); } + | classAttr IMPORT_ { $$ = (CorRegTypeAttr) ($1 | tdImport); } + | classAttr SERIALIZABLE_ { $$ = (CorRegTypeAttr) ($1 | tdSerializable); } + | classAttr WINDOWSRUNTIME_ { $$ = (CorRegTypeAttr) ($1 | tdWindowsRuntime); } + | classAttr NESTED_ PUBLIC_ { $$ = (CorRegTypeAttr) (($1 & ~tdVisibilityMask) | tdNestedPublic); } + | classAttr NESTED_ PRIVATE_ { $$ = (CorRegTypeAttr) (($1 & ~tdVisibilityMask) | tdNestedPrivate); } + | classAttr NESTED_ FAMILY_ { $$ = (CorRegTypeAttr) (($1 & ~tdVisibilityMask) | tdNestedFamily); } + | classAttr NESTED_ ASSEMBLY_ { $$ = (CorRegTypeAttr) (($1 & ~tdVisibilityMask) | tdNestedAssembly); } + | classAttr NESTED_ FAMANDASSEM_ { $$ = (CorRegTypeAttr) (($1 & ~tdVisibilityMask) | tdNestedFamANDAssem); } + | classAttr NESTED_ FAMORASSEM_ { $$ = (CorRegTypeAttr) (($1 & ~tdVisibilityMask) | tdNestedFamORAssem); } + | classAttr BEFOREFIELDINIT_ { $$ = (CorRegTypeAttr) ($1 | tdBeforeFieldInit); } + | classAttr SPECIALNAME_ { $$ = (CorRegTypeAttr) ($1 | tdSpecialName); } + | classAttr RTSPECIALNAME_ { $$ = (CorRegTypeAttr) ($1); } + | classAttr FLAGS_ '(' int32 ')' { $$ = (CorRegTypeAttr) ($4); } + ; + +extendsClause : /* EMPTY */ + | EXTENDS_ typeSpec { PASM->m_crExtends = $2; } + ; + +implClause : /* EMPTY */ + | IMPLEMENTS_ implList + ; + +classDecls : /* EMPTY */ + | classDecls classDecl + ; + +implList : implList ',' typeSpec { PASM->AddToImplList($3); } + | typeSpec { PASM->AddToImplList($1); } + ; + +/* Generic type parameters declaration */ +typeList : /* EMPTY */ { $$ = new BinStr(); } + | typeListNotEmpty { $$ = $1; } + ; + +typeListNotEmpty : typeSpec { $$ = new BinStr(); $$->appendInt32($1); } + | typeListNotEmpty ',' typeSpec { $$ = $1; $$->appendInt32($3); } + ; + +typarsClause : /* EMPTY */ { $$ = NULL; PASM->m_TyParList = NULL;} + | '<' typars '>' { $$ = $2; PASM->m_TyParList = $2;} + ; + +typarAttrib : '+' { $$ = gpCovariant; } + | '-' { $$ = gpContravariant; } + | CLASS_ { $$ = gpReferenceTypeConstraint; } + | VALUETYPE_ { $$ = gpNotNullableValueTypeConstraint; } + | _CTOR { $$ = gpDefaultConstructorConstraint; } + ; + +typarAttribs : /* EMPTY */ { $$ = 0; } + | typarAttrib typarAttribs { $$ = $1 | $2; } + ; + +typars : typarAttribs tyBound dottedName typarsRest {$$ = new TyParList($1, $2, $3, $4);} + | typarAttribs dottedName typarsRest {$$ = new TyParList($1, NULL, $2, $3);} + ; + +typarsRest : /* EMPTY */ { $$ = NULL; } + | ',' typars { $$ = $2; } + ; + +tyBound : '(' typeList ')' { $$ = $2; } + ; + +genArity : /* EMPTY */ { $$= 0; } + | genArityNotEmpty { $$ = $1; } + ; + +genArityNotEmpty : '<' '[' int32 ']' '>' { $$ = $3; } + ; + +/* Class body declarations */ +classDecl : methodHead methodDecls '}' { if(PASM->m_pCurMethod->m_ulLines[1] ==0) + { PASM->m_pCurMethod->m_ulLines[1] = PASM->m_ulCurLine; + PASM->m_pCurMethod->m_ulColumns[1]=PASM->m_ulCurColumn;} + PASM->EndMethod(); } + | classHead '{' classDecls '}' { PASM->EndClass(); } + | eventHead '{' eventDecls '}' { PASM->EndEvent(); } + | propHead '{' propDecls '}' { PASM->EndProp(); } + | fieldDecl + | dataDecl + | secDecl + | extSourceSpec + | customAttrDecl + | _SIZE int32 { PASM->m_pCurClass->m_ulSize = $2; } + | _PACK int32 { PASM->m_pCurClass->m_ulPack = $2; } + | exportHead '{' exptypeDecls '}' { PASMM->EndComType(); } + | _OVERRIDE typeSpec DCOLON methodName WITH_ callConv type typeSpec DCOLON methodName '(' sigArgs0 ')' + { BinStr *sig1 = parser->MakeSig($6, $7, $12); + BinStr *sig2 = new BinStr(); sig2->append(sig1); + PASM->AddMethodImpl($2,$4,sig1,$8,$10,sig2); + PASM->ResetArgNameList(); + } + | _OVERRIDE METHOD_ callConv type typeSpec DCOLON methodName genArity '(' sigArgs0 ')' WITH_ METHOD_ callConv type typeSpec DCOLON methodName genArity '(' sigArgs0 ')' + { PASM->AddMethodImpl($5,$7, + ($8==0 ? parser->MakeSig($3,$4,$10) : + parser->MakeSig($3| IMAGE_CEE_CS_CALLCONV_GENERIC,$4,$10,$8)), + $16,$18, + ($19==0 ? parser->MakeSig($14,$15,$21) : + parser->MakeSig($14| IMAGE_CEE_CS_CALLCONV_GENERIC,$15,$21,$19))); + PASM->ResetArgNameList(); + } + | languageDecl + | compControl + | PARAM_ TYPE_ '[' int32 ']' { if(($4 > 0) && ($4 <= (int)PASM->m_pCurClass->m_NumTyPars)) + PASM->m_pCustomDescrList = PASM->m_pCurClass->m_TyPars[$4-1].CAList(); + else + PASM->report->error("Type parameter index out of range\n"); + } + | PARAM_ TYPE_ dottedName { int n = PASM->m_pCurClass->FindTyPar($3); + if(n >= 0) + PASM->m_pCustomDescrList = PASM->m_pCurClass->m_TyPars[n].CAList(); + else + PASM->report->error("Type parameter '%s' undefined\n",$3); + } + | _INTERFACEIMPL TYPE_ typeSpec customDescr { $4->tkInterfacePair = $3; + if(PASM->m_pCustomDescrList) + PASM->m_pCustomDescrList->PUSH($4); + } + ; + +/* Field declaration */ +fieldDecl : _FIELD repeatOpt fieldAttr type dottedName atOpt initOpt + { $4->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + PASM->AddField($5, $4, $3, $6, $7, $2); } + ; + +fieldAttr : /* EMPTY */ { $$ = (CorFieldAttr) 0; } + | fieldAttr STATIC_ { $$ = (CorFieldAttr) ($1 | fdStatic); } + | fieldAttr PUBLIC_ { $$ = (CorFieldAttr) (($1 & ~mdMemberAccessMask) | fdPublic); } + | fieldAttr PRIVATE_ { $$ = (CorFieldAttr) (($1 & ~mdMemberAccessMask) | fdPrivate); } + | fieldAttr FAMILY_ { $$ = (CorFieldAttr) (($1 & ~mdMemberAccessMask) | fdFamily); } + | fieldAttr INITONLY_ { $$ = (CorFieldAttr) ($1 | fdInitOnly); } + | fieldAttr RTSPECIALNAME_ { $$ = $1; } /*{ $$ = (CorFieldAttr) ($1 | fdRTSpecialName); }*/ + | fieldAttr SPECIALNAME_ { $$ = (CorFieldAttr) ($1 | fdSpecialName); } + /* <STRIP>commented out because PInvoke for fields is not supported by EE + | fieldAttr PINVOKEIMPL_ '(' compQstring AS_ compQstring pinvAttr ')' + { $$ = (CorFieldAttr) ($1 | fdPinvokeImpl); + PASM->SetPinvoke($4,0,$6,$7); } + | fieldAttr PINVOKEIMPL_ '(' compQstring pinvAttr ')' + { $$ = (CorFieldAttr) ($1 | fdPinvokeImpl); + PASM->SetPinvoke($4,0,NULL,$5); } + | fieldAttr PINVOKEIMPL_ '(' pinvAttr ')' + { PASM->SetPinvoke(new BinStr(),0,NULL,$4); + $$ = (CorFieldAttr) ($1 | fdPinvokeImpl); } + </STRIP>*/ + | fieldAttr MARSHAL_ '(' marshalBlob ')' + { PASM->m_pMarshal = $4; } + | fieldAttr ASSEMBLY_ { $$ = (CorFieldAttr) (($1 & ~mdMemberAccessMask) | fdAssembly); } + | fieldAttr FAMANDASSEM_ { $$ = (CorFieldAttr) (($1 & ~mdMemberAccessMask) | fdFamANDAssem); } + | fieldAttr FAMORASSEM_ { $$ = (CorFieldAttr) (($1 & ~mdMemberAccessMask) | fdFamORAssem); } + | fieldAttr PRIVATESCOPE_ { $$ = (CorFieldAttr) (($1 & ~mdMemberAccessMask) | fdPrivateScope); } + | fieldAttr LITERAL_ { $$ = (CorFieldAttr) ($1 | fdLiteral); } + | fieldAttr NOTSERIALIZED_ { $$ = (CorFieldAttr) ($1 | fdNotSerialized); } + | fieldAttr FLAGS_ '(' int32 ')' { $$ = (CorFieldAttr) ($4); } + ; + +atOpt : /* EMPTY */ { $$ = 0; } + | AT_ id { $$ = $2; } + ; + +initOpt : /* EMPTY */ { $$ = NULL; } + | '=' fieldInit { $$ = $2; } + ; + +repeatOpt : /* EMPTY */ { $$ = 0xFFFFFFFF; } + | '[' int32 ']' { $$ = $2; } + ; + +/* Method referencing */ +methodRef : callConv type typeSpec DCOLON methodName tyArgs0 '(' sigArgs0 ')' + { PASM->ResetArgNameList(); + if ($6 == NULL) + { + if((iCallConv)&&(($1 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + $$ = PASM->MakeMemberRef($3, $5, parser->MakeSig($1|iCallConv, $2, $8)); + } + else + { + mdToken mr; + if((iCallConv)&&(($1 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + mr = PASM->MakeMemberRef($3, $5, + parser->MakeSig($1 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, $2, $8, corCountArgs($6))); + $$ = PASM->MakeMethodSpec(mr, + parser->MakeSig(IMAGE_CEE_CS_CALLCONV_INSTANTIATION, 0, $6)); + } + } + | callConv type typeSpec DCOLON methodName genArityNotEmpty '(' sigArgs0 ')' + { PASM->ResetArgNameList(); + if((iCallConv)&&(($1 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + $$ = PASM->MakeMemberRef($3, $5, + parser->MakeSig($1 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, $2, $8, $6)); + } + | callConv type methodName tyArgs0 '(' sigArgs0 ')' + { PASM->ResetArgNameList(); + if ($4 == NULL) + { + if((iCallConv)&&(($1 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + $$ = PASM->MakeMemberRef(mdTokenNil, $3, parser->MakeSig($1|iCallConv, $2, $6)); + } + else + { + mdToken mr; + if((iCallConv)&&(($1 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + mr = PASM->MakeMemberRef(mdTokenNil, $3, parser->MakeSig($1 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, $2, $6, corCountArgs($4))); + $$ = PASM->MakeMethodSpec(mr, + parser->MakeSig(IMAGE_CEE_CS_CALLCONV_INSTANTIATION, 0, $4)); + } + } + | callConv type methodName genArityNotEmpty '(' sigArgs0 ')' + { PASM->ResetArgNameList(); + if((iCallConv)&&(($1 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + $$ = PASM->MakeMemberRef(mdTokenNil, $3, parser->MakeSig($1 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, $2, $6, $4)); + } + | mdtoken { $$ = $1; } + | TYPEDEF_M { $$ = $1->m_tkTypeSpec; } + | TYPEDEF_MR { $$ = $1->m_tkTypeSpec; } + ; + +callConv : INSTANCE_ callConv { $$ = ($2 | IMAGE_CEE_CS_CALLCONV_HASTHIS); } + | EXPLICIT_ callConv { $$ = ($2 | IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS); } + | callKind { $$ = $1; } + | CALLCONV_ '(' int32 ')' { $$ = $3; } + ; + +callKind : /* EMPTY */ { $$ = IMAGE_CEE_CS_CALLCONV_DEFAULT; } + | DEFAULT_ { $$ = IMAGE_CEE_CS_CALLCONV_DEFAULT; } + | VARARG_ { $$ = IMAGE_CEE_CS_CALLCONV_VARARG; } + | UNMANAGED_ CDECL_ { $$ = IMAGE_CEE_CS_CALLCONV_C; } + | UNMANAGED_ STDCALL_ { $$ = IMAGE_CEE_CS_CALLCONV_STDCALL; } + | UNMANAGED_ THISCALL_ { $$ = IMAGE_CEE_CS_CALLCONV_THISCALL; } + | UNMANAGED_ FASTCALL_ { $$ = IMAGE_CEE_CS_CALLCONV_FASTCALL; } + ; + +mdtoken : MDTOKEN_ '(' int32 ')' { $$ = $3; } + ; + +memberRef : methodSpec methodRef { $$ = $2; + PASM->delArgNameList(PASM->m_firstArgName); + PASM->m_firstArgName = parser->m_ANSFirst.POP(); + PASM->m_lastArgName = parser->m_ANSLast.POP(); + PASM->SetMemberRefFixup($2,iOpcodeLen); } + | FIELD_ type typeSpec DCOLON dottedName + { $2->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + $$ = PASM->MakeMemberRef($3, $5, $2); + PASM->SetMemberRefFixup($$,iOpcodeLen); } + | FIELD_ type dottedName + { $2->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + $$ = PASM->MakeMemberRef(NULL, $3, $2); + PASM->SetMemberRefFixup($$,iOpcodeLen); } + | FIELD_ TYPEDEF_F { $$ = $2->m_tkTypeSpec; + PASM->SetMemberRefFixup($$,iOpcodeLen); } + | FIELD_ TYPEDEF_MR { $$ = $2->m_tkTypeSpec; + PASM->SetMemberRefFixup($$,iOpcodeLen); } + | mdtoken { $$ = $1; + PASM->SetMemberRefFixup($$,iOpcodeLen); } + ; + +/* Event declaration */ +eventHead : _EVENT eventAttr typeSpec dottedName { PASM->ResetEvent($4, $3, $2); } + | _EVENT eventAttr dottedName { PASM->ResetEvent($3, mdTypeRefNil, $2); } + ; + + +eventAttr : /* EMPTY */ { $$ = (CorEventAttr) 0; } + | eventAttr RTSPECIALNAME_ { $$ = $1; }/*{ $$ = (CorEventAttr) ($1 | evRTSpecialName); }*/ + | eventAttr SPECIALNAME_ { $$ = (CorEventAttr) ($1 | evSpecialName); } + ; + +eventDecls : /* EMPTY */ + | eventDecls eventDecl + ; + +eventDecl : _ADDON methodRef { PASM->SetEventMethod(0, $2); } + | _REMOVEON methodRef { PASM->SetEventMethod(1, $2); } + | _FIRE methodRef { PASM->SetEventMethod(2, $2); } + | _OTHER methodRef { PASM->SetEventMethod(3, $2); } + | extSourceSpec + | customAttrDecl + | languageDecl + | compControl + ; + +/* Property declaration */ +propHead : _PROPERTY propAttr callConv type dottedName '(' sigArgs0 ')' initOpt + { PASM->ResetProp($5, + parser->MakeSig((IMAGE_CEE_CS_CALLCONV_PROPERTY | + ($3 & IMAGE_CEE_CS_CALLCONV_HASTHIS)),$4,$7), $2, $9);} + ; + +propAttr : /* EMPTY */ { $$ = (CorPropertyAttr) 0; } + | propAttr RTSPECIALNAME_ { $$ = $1; }/*{ $$ = (CorPropertyAttr) ($1 | prRTSpecialName); }*/ + | propAttr SPECIALNAME_ { $$ = (CorPropertyAttr) ($1 | prSpecialName); } + ; + +propDecls : /* EMPTY */ + | propDecls propDecl + ; + + +propDecl : _SET methodRef { PASM->SetPropMethod(0, $2); } + | _GET methodRef { PASM->SetPropMethod(1, $2); } + | _OTHER methodRef { PASM->SetPropMethod(2, $2); } + | customAttrDecl + | extSourceSpec + | languageDecl + | compControl + ; + +/* Method declaration */ +methodHeadPart1 : _METHOD { PASM->ResetForNextMethod(); + uMethodBeginLine = PASM->m_ulCurLine; + uMethodBeginColumn=PASM->m_ulCurColumn; + } + ; + +marshalClause : /* EMPTY */ { $$ = NULL; } + | MARSHAL_ '(' marshalBlob ')' { $$ = $3; } + ; + +marshalBlob : nativeType { $$ = $1; } + | marshalBlobHead hexbytes '}' { $$ = $2; } + ; + +marshalBlobHead : '{' { bParsingByteArray = TRUE; } + ; + +methodHead : methodHeadPart1 methAttr callConv paramAttr type marshalClause methodName typarsClause'(' sigArgs0 ')' implAttr '{' + { BinStr* sig; + if ($8 == NULL) sig = parser->MakeSig($3, $5, $10); + else { + FixupTyPars($5); + sig = parser->MakeSig($3 | IMAGE_CEE_CS_CALLCONV_GENERIC, $5, $10, $8->Count()); + FixupConstraints(); + } + PASM->StartMethod($7, sig, $2, $6, $4, $8); + TyParFixupList.RESET(false); + PASM->SetImplAttr((USHORT)$12); + PASM->m_pCurMethod->m_ulLines[0] = uMethodBeginLine; + PASM->m_pCurMethod->m_ulColumns[0]=uMethodBeginColumn; + } + ; + +methAttr : /* EMPTY */ { $$ = (CorMethodAttr) 0; } + | methAttr STATIC_ { $$ = (CorMethodAttr) ($1 | mdStatic); } + | methAttr PUBLIC_ { $$ = (CorMethodAttr) (($1 & ~mdMemberAccessMask) | mdPublic); } + | methAttr PRIVATE_ { $$ = (CorMethodAttr) (($1 & ~mdMemberAccessMask) | mdPrivate); } + | methAttr FAMILY_ { $$ = (CorMethodAttr) (($1 & ~mdMemberAccessMask) | mdFamily); } + | methAttr FINAL_ { $$ = (CorMethodAttr) ($1 | mdFinal); } + | methAttr SPECIALNAME_ { $$ = (CorMethodAttr) ($1 | mdSpecialName); } + | methAttr VIRTUAL_ { $$ = (CorMethodAttr) ($1 | mdVirtual); } + | methAttr STRICT_ { $$ = (CorMethodAttr) ($1 | mdCheckAccessOnOverride); } + | methAttr ABSTRACT_ { $$ = (CorMethodAttr) ($1 | mdAbstract); } + | methAttr ASSEMBLY_ { $$ = (CorMethodAttr) (($1 & ~mdMemberAccessMask) | mdAssem); } + | methAttr FAMANDASSEM_ { $$ = (CorMethodAttr) (($1 & ~mdMemberAccessMask) | mdFamANDAssem); } + | methAttr FAMORASSEM_ { $$ = (CorMethodAttr) (($1 & ~mdMemberAccessMask) | mdFamORAssem); } + | methAttr PRIVATESCOPE_ { $$ = (CorMethodAttr) (($1 & ~mdMemberAccessMask) | mdPrivateScope); } + | methAttr HIDEBYSIG_ { $$ = (CorMethodAttr) ($1 | mdHideBySig); } + | methAttr NEWSLOT_ { $$ = (CorMethodAttr) ($1 | mdNewSlot); } + | methAttr RTSPECIALNAME_ { $$ = $1; }/*{ $$ = (CorMethodAttr) ($1 | mdRTSpecialName); }*/ + | methAttr UNMANAGEDEXP_ { $$ = (CorMethodAttr) ($1 | mdUnmanagedExport); } + | methAttr REQSECOBJ_ { $$ = (CorMethodAttr) ($1 | mdRequireSecObject); } + | methAttr FLAGS_ '(' int32 ')' { $$ = (CorMethodAttr) ($4); } + | methAttr PINVOKEIMPL_ '(' compQstring AS_ compQstring pinvAttr ')' + { PASM->SetPinvoke($4,0,$6,$7); + $$ = (CorMethodAttr) ($1 | mdPinvokeImpl); } + | methAttr PINVOKEIMPL_ '(' compQstring pinvAttr ')' + { PASM->SetPinvoke($4,0,NULL,$5); + $$ = (CorMethodAttr) ($1 | mdPinvokeImpl); } + | methAttr PINVOKEIMPL_ '(' pinvAttr ')' + { PASM->SetPinvoke(new BinStr(),0,NULL,$4); + $$ = (CorMethodAttr) ($1 | mdPinvokeImpl); } + ; + +pinvAttr : /* EMPTY */ { $$ = (CorPinvokeMap) 0; } + | pinvAttr NOMANGLE_ { $$ = (CorPinvokeMap) ($1 | pmNoMangle); } + | pinvAttr ANSI_ { $$ = (CorPinvokeMap) ($1 | pmCharSetAnsi); } + | pinvAttr UNICODE_ { $$ = (CorPinvokeMap) ($1 | pmCharSetUnicode); } + | pinvAttr AUTOCHAR_ { $$ = (CorPinvokeMap) ($1 | pmCharSetAuto); } + | pinvAttr LASTERR_ { $$ = (CorPinvokeMap) ($1 | pmSupportsLastError); } + | pinvAttr WINAPI_ { $$ = (CorPinvokeMap) ($1 | pmCallConvWinapi); } + | pinvAttr CDECL_ { $$ = (CorPinvokeMap) ($1 | pmCallConvCdecl); } + | pinvAttr STDCALL_ { $$ = (CorPinvokeMap) ($1 | pmCallConvStdcall); } + | pinvAttr THISCALL_ { $$ = (CorPinvokeMap) ($1 | pmCallConvThiscall); } + | pinvAttr FASTCALL_ { $$ = (CorPinvokeMap) ($1 | pmCallConvFastcall); } + | pinvAttr BESTFIT_ ':' ON_ { $$ = (CorPinvokeMap) ($1 | pmBestFitEnabled); } + | pinvAttr BESTFIT_ ':' OFF_ { $$ = (CorPinvokeMap) ($1 | pmBestFitDisabled); } + | pinvAttr CHARMAPERROR_ ':' ON_ { $$ = (CorPinvokeMap) ($1 | pmThrowOnUnmappableCharEnabled); } + | pinvAttr CHARMAPERROR_ ':' OFF_ { $$ = (CorPinvokeMap) ($1 | pmThrowOnUnmappableCharDisabled); } + | pinvAttr FLAGS_ '(' int32 ')' { $$ = (CorPinvokeMap) ($4); } + ; + +methodName : _CTOR { $$ = newString(COR_CTOR_METHOD_NAME); } + | _CCTOR { $$ = newString(COR_CCTOR_METHOD_NAME); } + | dottedName { $$ = $1; } + ; + +paramAttr : /* EMPTY */ { $$ = 0; } + | paramAttr '[' IN_ ']' { $$ = $1 | pdIn; } + | paramAttr '[' OUT_ ']' { $$ = $1 | pdOut; } + | paramAttr '[' OPT_ ']' { $$ = $1 | pdOptional; } + | paramAttr '[' int32 ']' { $$ = $3 + 1; } + ; + +implAttr : /* EMPTY */ { $$ = (CorMethodImpl) (miIL | miManaged); } + | implAttr NATIVE_ { $$ = (CorMethodImpl) (($1 & 0xFFF4) | miNative); } + | implAttr CIL_ { $$ = (CorMethodImpl) (($1 & 0xFFF4) | miIL); } + | implAttr OPTIL_ { $$ = (CorMethodImpl) (($1 & 0xFFF4) | miOPTIL); } + | implAttr MANAGED_ { $$ = (CorMethodImpl) (($1 & 0xFFFB) | miManaged); } + | implAttr UNMANAGED_ { $$ = (CorMethodImpl) (($1 & 0xFFFB) | miUnmanaged); } + | implAttr FORWARDREF_ { $$ = (CorMethodImpl) ($1 | miForwardRef); } + | implAttr PRESERVESIG_ { $$ = (CorMethodImpl) ($1 | miPreserveSig); } + | implAttr RUNTIME_ { $$ = (CorMethodImpl) ($1 | miRuntime); } + | implAttr INTERNALCALL_ { $$ = (CorMethodImpl) ($1 | miInternalCall); } + | implAttr SYNCHRONIZED_ { $$ = (CorMethodImpl) ($1 | miSynchronized); } + | implAttr NOINLINING_ { $$ = (CorMethodImpl) ($1 | miNoInlining); } + | implAttr AGGRESSIVEINLINING_ { $$ = (CorMethodImpl) ($1 | miAggressiveInlining); } + | implAttr NOOPTIMIZATION_ { $$ = (CorMethodImpl) ($1 | miNoOptimization); } + | implAttr FLAGS_ '(' int32 ')' { $$ = (CorMethodImpl) ($4); } + ; + +localsHead : _LOCALS { PASM->delArgNameList(PASM->m_firstArgName); PASM->m_firstArgName = NULL;PASM->m_lastArgName = NULL; + } + ; + +methodDecls : /* EMPTY */ + | methodDecls methodDecl + ; + +methodDecl : _EMITBYTE int32 { PASM->EmitByte($2); } + | sehBlock { delete PASM->m_SEHD; PASM->m_SEHD = PASM->m_SEHDstack.POP(); } + | _MAXSTACK int32 { PASM->EmitMaxStack($2); } + | localsHead '(' sigArgs0 ')' { PASM->EmitLocals(parser->MakeSig(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG, 0, $3)); + } + | localsHead INIT_ '(' sigArgs0 ')' { PASM->EmitZeroInit(); + PASM->EmitLocals(parser->MakeSig(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG, 0, $4)); + } + | _ENTRYPOINT { PASM->EmitEntryPoint(); } + | _ZEROINIT { PASM->EmitZeroInit(); } + | dataDecl + | instr + | id ':' { PASM->AddLabel(PASM->m_CurPC,$1); /*PASM->EmitLabel($1);*/ } + | secDecl + | extSourceSpec + | languageDecl + | customAttrDecl + | compControl + | _EXPORT '[' int32 ']' { if(PASM->m_pCurMethod->m_dwExportOrdinal == 0xFFFFFFFF) + { + PASM->m_pCurMethod->m_dwExportOrdinal = $3; + PASM->m_pCurMethod->m_szExportAlias = NULL; + if(PASM->m_pCurMethod->m_wVTEntry == 0) PASM->m_pCurMethod->m_wVTEntry = 1; + if(PASM->m_pCurMethod->m_wVTSlot == 0) PASM->m_pCurMethod->m_wVTSlot = $3 + 0x8000; + } + else + PASM->report->warn("Duplicate .export directive, ignored\n"); + } + | _EXPORT '[' int32 ']' AS_ id { if(PASM->m_pCurMethod->m_dwExportOrdinal == 0xFFFFFFFF) + { + PASM->m_pCurMethod->m_dwExportOrdinal = $3; + PASM->m_pCurMethod->m_szExportAlias = $6; + if(PASM->m_pCurMethod->m_wVTEntry == 0) PASM->m_pCurMethod->m_wVTEntry = 1; + if(PASM->m_pCurMethod->m_wVTSlot == 0) PASM->m_pCurMethod->m_wVTSlot = $3 + 0x8000; + } + else + PASM->report->warn("Duplicate .export directive, ignored\n"); + } + | _VTENTRY int32 ':' int32 { PASM->m_pCurMethod->m_wVTEntry = (WORD)$2; + PASM->m_pCurMethod->m_wVTSlot = (WORD)$4; } + | _OVERRIDE typeSpec DCOLON methodName + { PASM->AddMethodImpl($2,$4,NULL,NULL,NULL,NULL); } + + | _OVERRIDE METHOD_ callConv type typeSpec DCOLON methodName genArity '(' sigArgs0 ')' + { PASM->AddMethodImpl($5,$7, + ($8==0 ? parser->MakeSig($3,$4,$10) : + parser->MakeSig($3| IMAGE_CEE_CS_CALLCONV_GENERIC,$4,$10,$8)) + ,NULL,NULL,NULL); + PASM->ResetArgNameList(); + } + | scopeBlock + | PARAM_ TYPE_ '[' int32 ']' { if(($4 > 0) && ($4 <= (int)PASM->m_pCurMethod->m_NumTyPars)) + PASM->m_pCustomDescrList = PASM->m_pCurMethod->m_TyPars[$4-1].CAList(); + else + PASM->report->error("Type parameter index out of range\n"); + } + | PARAM_ TYPE_ dottedName { int n = PASM->m_pCurMethod->FindTyPar($3); + if(n >= 0) + PASM->m_pCustomDescrList = PASM->m_pCurMethod->m_TyPars[n].CAList(); + else + PASM->report->error("Type parameter '%s' undefined\n",$3); + } + | PARAM_ '[' int32 ']' initOpt + { if( $3 ) { + ARG_NAME_LIST* pAN=PASM->findArg(PASM->m_pCurMethod->m_firstArgName, $3 - 1); + if(pAN) + { + PASM->m_pCustomDescrList = &(pAN->CustDList); + pAN->pValue = $5; + } + else + { + PASM->m_pCustomDescrList = NULL; + if($5) delete $5; + } + } else { + PASM->m_pCustomDescrList = &(PASM->m_pCurMethod->m_RetCustDList); + PASM->m_pCurMethod->m_pRetValue = $5; + } + PASM->m_tkCurrentCVOwner = 0; + } + ; + +scopeBlock : scopeOpen methodDecls '}' { PASM->m_pCurMethod->CloseScope(); } + ; + +scopeOpen : '{' { PASM->m_pCurMethod->OpenScope(); } + ; + +/* Structured exception handling directives */ +sehBlock : tryBlock sehClauses + ; + +sehClauses : sehClause sehClauses + | sehClause + ; + +tryBlock : tryHead scopeBlock { PASM->m_SEHD->tryTo = PASM->m_CurPC; } + | tryHead id TO_ id { PASM->SetTryLabels($2, $4); } + | tryHead int32 TO_ int32 { if(PASM->m_SEHD) {PASM->m_SEHD->tryFrom = $2; + PASM->m_SEHD->tryTo = $4;} } + ; + +tryHead : _TRY { PASM->NewSEHDescriptor(); + PASM->m_SEHD->tryFrom = PASM->m_CurPC; } + ; + + +sehClause : catchClause handlerBlock { PASM->EmitTry(); } + | filterClause handlerBlock { PASM->EmitTry(); } + | finallyClause handlerBlock { PASM->EmitTry(); } + | faultClause handlerBlock { PASM->EmitTry(); } + ; + + +filterClause : filterHead scopeBlock { PASM->m_SEHD->sehHandler = PASM->m_CurPC; } + | filterHead id { PASM->SetFilterLabel($2); + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } + | filterHead int32 { PASM->m_SEHD->sehFilter = $2; + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } + ; + +filterHead : FILTER_ { PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FILTER; + PASM->m_SEHD->sehFilter = PASM->m_CurPC; } + ; + +catchClause : CATCH_ typeSpec { PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_NONE; + PASM->SetCatchClass($2); + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } + ; + +finallyClause : FINALLY_ { PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FINALLY; + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } + ; + +faultClause : FAULT_ { PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FAULT; + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } + ; + +handlerBlock : scopeBlock { PASM->m_SEHD->sehHandlerTo = PASM->m_CurPC; } + | HANDLER_ id TO_ id { PASM->SetHandlerLabels($2, $4); } + | HANDLER_ int32 TO_ int32 { PASM->m_SEHD->sehHandler = $2; + PASM->m_SEHD->sehHandlerTo = $4; } + ; + +/* Data declaration */ +dataDecl : ddHead ddBody + ; + +ddHead : _DATA tls id '=' { PASM->EmitDataLabel($3); } + | _DATA tls + ; + +tls : /* EMPTY */ { PASM->SetDataSection(); } + | TLS_ { PASM->SetTLSSection(); } + | CIL_ { PASM->SetILSection(); } + ; + +ddBody : '{' ddItemList '}' + | ddItem + ; + +ddItemList : ddItem ',' ddItemList + | ddItem + ; + +ddItemCount : /* EMPTY */ { $$ = 1; } + | '[' int32 ']' { $$ = $2; + if($2 <= 0) { PASM->report->error("Illegal item count: %d\n",$2); + if(!PASM->OnErrGo) $$ = 1; }} + ; + +ddItem : CHAR_ '*' '(' compQstring ')' { PASM->EmitDataString($4); } + | '&' '(' id ')' { PASM->EmitDD($3); } + | bytearrayhead bytes ')' { PASM->EmitData($2->ptr(),$2->length()); } + | FLOAT32_ '(' float64 ')' ddItemCount + { float f = (float) (*$3); float* p = new (nothrow) float[$5]; + if(p != NULL) { + for(int i=0; i < $5; i++) p[i] = f; + PASM->EmitData(p, sizeof(float)*$5); delete $3; delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(float)*$5); } + | FLOAT64_ '(' float64 ')' ddItemCount + { double* p = new (nothrow) double[$5]; + if(p != NULL) { + for(int i=0; i<$5; i++) p[i] = *($3); + PASM->EmitData(p, sizeof(double)*$5); delete $3; delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(double)*$5); } + | INT64_ '(' int64 ')' ddItemCount + { __int64* p = new (nothrow) __int64[$5]; + if(p != NULL) { + for(int i=0; i<$5; i++) p[i] = *($3); + PASM->EmitData(p, sizeof(__int64)*$5); delete $3; delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(__int64)*$5); } + | INT32_ '(' int32 ')' ddItemCount + { __int32* p = new (nothrow) __int32[$5]; + if(p != NULL) { + for(int i=0; i<$5; i++) p[i] = $3; + PASM->EmitData(p, sizeof(__int32)*$5); delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(__int32)*$5); } + | INT16_ '(' int32 ')' ddItemCount + { __int16 i = (__int16) $3; FAIL_UNLESS(i == $3, ("Value %d too big\n", $3)); + __int16* p = new (nothrow) __int16[$5]; + if(p != NULL) { + for(int j=0; j<$5; j++) p[j] = i; + PASM->EmitData(p, sizeof(__int16)*$5); delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(__int16)*$5); } + | INT8_ '(' int32 ')' ddItemCount + { __int8 i = (__int8) $3; FAIL_UNLESS(i == $3, ("Value %d too big\n", $3)); + __int8* p = new (nothrow) __int8[$5]; + if(p != NULL) { + for(int j=0; j<$5; j++) p[j] = i; + PASM->EmitData(p, sizeof(__int8)*$5); delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(__int8)*$5); } + | FLOAT32_ ddItemCount { PASM->EmitData(NULL, sizeof(float)*$2); } + | FLOAT64_ ddItemCount { PASM->EmitData(NULL, sizeof(double)*$2); } + | INT64_ ddItemCount { PASM->EmitData(NULL, sizeof(__int64)*$2); } + | INT32_ ddItemCount { PASM->EmitData(NULL, sizeof(__int32)*$2); } + | INT16_ ddItemCount { PASM->EmitData(NULL, sizeof(__int16)*$2); } + | INT8_ ddItemCount { PASM->EmitData(NULL, sizeof(__int8)*$2); } + ; + +/* Default values declaration for fields, parameters and verbal form of CA blob description */ +fieldSerInit : FLOAT32_ '(' float64 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_R4); + float f = (float)(*$3); + $$->appendInt32(*((__int32*)&f)); delete $3; } + | FLOAT64_ '(' float64 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_R8); + $$->appendInt64((__int64 *)$3); delete $3; } + | FLOAT32_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_R4); + $$->appendInt32($3); } + | FLOAT64_ '(' int64 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_R8); + $$->appendInt64((__int64 *)$3); delete $3; } + | INT64_ '(' int64 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I8); + $$->appendInt64((__int64 *)$3); delete $3; } + | INT32_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I4); + $$->appendInt32($3); } + | INT16_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I2); + $$->appendInt16($3); } + | INT8_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I1); + $$->appendInt8($3); } + | UNSIGNED_ INT64_ '(' int64 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U8); + $$->appendInt64((__int64 *)$4); delete $4; } + | UNSIGNED_ INT32_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U4); + $$->appendInt32($4); } + | UNSIGNED_ INT16_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U2); + $$->appendInt16($4); } + | UNSIGNED_ INT8_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U1); + $$->appendInt8($4); } + | UINT64_ '(' int64 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U8); + $$->appendInt64((__int64 *)$3); delete $3; } + | UINT32_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U4); + $$->appendInt32($3); } + | UINT16_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U2); + $$->appendInt16($3); } + | UINT8_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U1); + $$->appendInt8($3); } + | CHAR_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_CHAR); + $$->appendInt16($3); } + | BOOL_ '(' truefalse ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_BOOLEAN); + $$->appendInt8($3);} + | bytearrayhead bytes ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_STRING); + $$->append($2); delete $2;} + ; + +bytearrayhead : BYTEARRAY_ '(' { bParsingByteArray = TRUE; } + ; + +bytes : /* EMPTY */ { $$ = new BinStr(); } + | hexbytes { $$ = $1; } + ; + +hexbytes : HEXBYTE { __int8 i = (__int8) $1; $$ = new BinStr(); $$->appendInt8(i); } + | hexbytes HEXBYTE { __int8 i = (__int8) $2; $$ = $1; $$->appendInt8(i); } + ; + +/* Field/parameter initialization */ +fieldInit : fieldSerInit { $$ = $1; } + | compQstring { $$ = BinStrToUnicode($1,true); $$->insertInt8(ELEMENT_TYPE_STRING);} + | NULLREF_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_CLASS); + $$->appendInt32(0); } + ; + +/* Values for verbal form of CA blob description */ +serInit : fieldSerInit { $$ = $1; } + | STRING_ '(' NULLREF_ ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_STRING); $$->appendInt8(0xFF); } + | STRING_ '(' SQSTRING ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_STRING); + AppendStringWithLength($$,$3); delete [] $3;} + | TYPE_ '(' CLASS_ SQSTRING ')' { $$ = new BinStr(); $$->appendInt8(SERIALIZATION_TYPE_TYPE); + AppendStringWithLength($$,$4); delete [] $4;} + | TYPE_ '(' className ')' { $$ = new BinStr(); $$->appendInt8(SERIALIZATION_TYPE_TYPE); + AppendStringWithLength($$,PASM->ReflectionNotation($3));} + | TYPE_ '(' NULLREF_ ')' { $$ = new BinStr(); $$->appendInt8(SERIALIZATION_TYPE_TYPE); $$->appendInt8(0xFF); } + | OBJECT_ '(' serInit ')' { $$ = $3; $$->insertInt8(SERIALIZATION_TYPE_TAGGED_OBJECT);} + | FLOAT32_ '[' int32 ']' '(' f32seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_R4); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | FLOAT64_ '[' int32 ']' '(' f64seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_R8); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | INT64_ '[' int32 ']' '(' i64seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_I8); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | INT32_ '[' int32 ']' '(' i32seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_I4); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | INT16_ '[' int32 ']' '(' i16seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_I2); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | INT8_ '[' int32 ']' '(' i8seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_I1); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | UINT64_ '[' int32 ']' '(' i64seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_U8); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | UINT32_ '[' int32 ']' '(' i32seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_U4); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | UINT16_ '[' int32 ']' '(' i16seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_U2); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | UINT8_ '[' int32 ']' '(' i8seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_U1); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | UNSIGNED_ INT64_ '[' int32 ']' '(' i64seq ')' + { $$ = $7; $$->insertInt32($4); + $$->insertInt8(ELEMENT_TYPE_U8); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | UNSIGNED_ INT32_ '[' int32 ']' '(' i32seq ')' + { $$ = $7; $$->insertInt32($4); + $$->insertInt8(ELEMENT_TYPE_U4); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | UNSIGNED_ INT16_ '[' int32 ']' '(' i16seq ')' + { $$ = $7; $$->insertInt32($4); + $$->insertInt8(ELEMENT_TYPE_U2); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | UNSIGNED_ INT8_ '[' int32 ']' '(' i8seq ')' + { $$ = $7; $$->insertInt32($4); + $$->insertInt8(ELEMENT_TYPE_U1); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | CHAR_ '[' int32 ']' '(' i16seq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_CHAR); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | BOOL_ '[' int32 ']' '(' boolSeq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_BOOLEAN); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | STRING_ '[' int32 ']' '(' sqstringSeq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(ELEMENT_TYPE_STRING); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | TYPE_ '[' int32 ']' '(' classSeq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(SERIALIZATION_TYPE_TYPE); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | OBJECT_ '[' int32 ']' '(' objSeq ')' + { $$ = $6; $$->insertInt32($3); + $$->insertInt8(SERIALIZATION_TYPE_TAGGED_OBJECT); + $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + ; + + +f32seq : /* EMPTY */ { $$ = new BinStr(); } + | f32seq float64 { $$ = $1; + float f = (float) (*$2); $$->appendInt32(*((__int32*)&f)); delete $2; } + | f32seq int32 { $$ = $1; + $$->appendInt32($2); } + ; + +f64seq : /* EMPTY */ { $$ = new BinStr(); } + | f64seq float64 { $$ = $1; + $$->appendInt64((__int64 *)$2); delete $2; } + | f64seq int64 { $$ = $1; + $$->appendInt64((__int64 *)$2); delete $2; } + ; + +i64seq : /* EMPTY */ { $$ = new BinStr(); } + | i64seq int64 { $$ = $1; + $$->appendInt64((__int64 *)$2); delete $2; } + ; + +i32seq : /* EMPTY */ { $$ = new BinStr(); } + | i32seq int32 { $$ = $1; $$->appendInt32($2);} + ; + +i16seq : /* EMPTY */ { $$ = new BinStr(); } + | i16seq int32 { $$ = $1; $$->appendInt16($2);} + ; + +i8seq : /* EMPTY */ { $$ = new BinStr(); } + | i8seq int32 { $$ = $1; $$->appendInt8($2); } + ; + +boolSeq : /* EMPTY */ { $$ = new BinStr(); } + | boolSeq truefalse { $$ = $1; + $$->appendInt8($2);} + ; + +sqstringSeq : /* EMPTY */ { $$ = new BinStr(); } + | sqstringSeq NULLREF_ { $$ = $1; $$->appendInt8(0xFF); } + | sqstringSeq SQSTRING { $$ = $1; + AppendStringWithLength($$,$2); delete [] $2;} + ; + +classSeq : /* EMPTY */ { $$ = new BinStr(); } + | classSeq NULLREF_ { $$ = $1; $$->appendInt8(0xFF); } + | classSeq CLASS_ SQSTRING { $$ = $1; + AppendStringWithLength($$,$3); delete [] $3;} + | classSeq className { $$ = $1; + AppendStringWithLength($$,PASM->ReflectionNotation($2));} + ; + +objSeq : /* EMPTY */ { $$ = new BinStr(); } + | objSeq serInit { $$ = $1; $$->append($2); delete $2; } + ; + +/* IL instructions and associated definitions */ +methodSpec : METHOD_ { parser->m_ANSFirst.PUSH(PASM->m_firstArgName); + parser->m_ANSLast.PUSH(PASM->m_lastArgName); + PASM->m_firstArgName = NULL; + PASM->m_lastArgName = NULL; } + ; + +instr_none : INSTR_NONE { $$ = SetupInstr($1); } + ; + +instr_var : INSTR_VAR { $$ = SetupInstr($1); } + ; + +instr_i : INSTR_I { $$ = SetupInstr($1); } + ; + +instr_i8 : INSTR_I8 { $$ = SetupInstr($1); } + ; + +instr_r : INSTR_R { $$ = SetupInstr($1); } + ; + +instr_brtarget : INSTR_BRTARGET { $$ = SetupInstr($1); } + ; + +instr_method : INSTR_METHOD { $$ = SetupInstr($1); + if((!PASM->OnErrGo)&& + (($1 == CEE_NEWOBJ)|| + ($1 == CEE_CALLVIRT))) + iCallConv = IMAGE_CEE_CS_CALLCONV_HASTHIS; + } + ; + +instr_field : INSTR_FIELD { $$ = SetupInstr($1); } + ; + +instr_type : INSTR_TYPE { $$ = SetupInstr($1); } + ; + +instr_string : INSTR_STRING { $$ = SetupInstr($1); } + ; + +instr_sig : INSTR_SIG { $$ = SetupInstr($1); } + ; + +instr_tok : INSTR_TOK { $$ = SetupInstr($1); iOpcodeLen = PASM->OpcodeLen($$); } + ; + +instr_switch : INSTR_SWITCH { $$ = SetupInstr($1); } + ; + +instr_r_head : instr_r '(' { $$ = $1; bParsingByteArray = TRUE; } + ; + + +instr : instr_none { PASM->EmitOpcode($1); } + | instr_var int32 { PASM->EmitInstrVar($1, $2); } + | instr_var id { PASM->EmitInstrVarByName($1, $2); } + | instr_i int32 { PASM->EmitInstrI($1, $2); } + | instr_i8 int64 { PASM->EmitInstrI8($1, $2); } + | instr_r float64 { PASM->EmitInstrR($1, $2); delete ($2);} + | instr_r int64 { double f = (double) (*$2); PASM->EmitInstrR($1, &f); } + | instr_r_head bytes ')' { unsigned L = $2->length(); + FAIL_UNLESS(L >= sizeof(float), ("%d hexbytes, must be at least %d\n", + L,sizeof(float))); + if(L < sizeof(float)) {YYERROR; } + else { + double f = (L >= sizeof(double)) ? *((double *)($2->ptr())) + : (double)(*(float *)($2->ptr())); + PASM->EmitInstrR($1,&f); } + delete $2; } + | instr_brtarget int32 { PASM->EmitInstrBrOffset($1, $2); } + | instr_brtarget id { PASM->EmitInstrBrTarget($1, $2); } + | instr_method methodRef + { PASM->SetMemberRefFixup($2,PASM->OpcodeLen($1)); + PASM->EmitInstrI($1,$2); + PASM->m_tkCurrentCVOwner = $2; + PASM->m_pCustomDescrList = NULL; + iCallConv = 0; + } + | instr_field type typeSpec DCOLON dottedName + { $2->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + mdToken mr = PASM->MakeMemberRef($3, $5, $2); + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen($1)); + PASM->EmitInstrI($1,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } + | instr_field type dottedName + { $2->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + mdToken mr = PASM->MakeMemberRef(mdTokenNil, $3, $2); + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen($1)); + PASM->EmitInstrI($1,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } + | instr_field mdtoken { mdToken mr = $2; + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen($1)); + PASM->EmitInstrI($1,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } + | instr_field TYPEDEF_F { mdToken mr = $2->m_tkTypeSpec; + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen($1)); + PASM->EmitInstrI($1,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } + | instr_field TYPEDEF_MR { mdToken mr = $2->m_tkTypeSpec; + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen($1)); + PASM->EmitInstrI($1,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } + | instr_type typeSpec { PASM->EmitInstrI($1, $2); + PASM->m_tkCurrentCVOwner = $2; + PASM->m_pCustomDescrList = NULL; + } + | instr_string compQstring { PASM->EmitInstrStringLiteral($1, $2,TRUE); } + | instr_string ANSI_ '(' compQstring ')' + { PASM->EmitInstrStringLiteral($1, $4,FALSE); } + | instr_string bytearrayhead bytes ')' + { PASM->EmitInstrStringLiteral($1, $3,FALSE,TRUE); } + | instr_sig callConv type '(' sigArgs0 ')' + { PASM->EmitInstrSig($1, parser->MakeSig($2, $3, $5)); + PASM->ResetArgNameList(); + } + | instr_tok ownerType /* ownerType ::= memberRef | typeSpec */ + { PASM->EmitInstrI($1,$2); + PASM->m_tkCurrentCVOwner = $2; + PASM->m_pCustomDescrList = NULL; + iOpcodeLen = 0; + } + | instr_switch '(' labels ')' { PASM->EmitInstrSwitch($1, $3); } + ; + +labels : /* empty */ { $$ = 0; } + | id ',' labels { $$ = new Labels($1, $3, TRUE); } + | int32 ',' labels { $$ = new Labels((char *)(UINT_PTR)$1, $3, FALSE); } + | id { $$ = new Labels($1, NULL, TRUE); } + | int32 { $$ = new Labels((char *)(UINT_PTR)$1, NULL, FALSE); } + ; + +/* Signatures */ +tyArgs0 : /* EMPTY */ { $$ = NULL; } + | '<' tyArgs1 '>' { $$ = $2; } + ; + +tyArgs1 : /* EMPTY */ { $$ = NULL; } + | tyArgs2 { $$ = $1; } + ; + +tyArgs2 : type { $$ = $1; } + | tyArgs2 ',' type { $$ = $1; $$->append($3); delete $3; } + ; + + +sigArgs0 : /* EMPTY */ { $$ = new BinStr(); } + | sigArgs1 { $$ = $1;} + ; + +sigArgs1 : sigArg { $$ = $1; } + | sigArgs1 ',' sigArg { $$ = $1; $$->append($3); delete $3; } + ; + +sigArg : ELIPSIS { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_SENTINEL); } + | paramAttr type marshalClause { $$ = new BinStr(); $$->append($2); PASM->addArgName(NULL, $2, $3, $1); } + | paramAttr type marshalClause id { $$ = new BinStr(); $$->append($2); PASM->addArgName($4, $2, $3, $1);} + ; + +/* Class referencing */ +className : '[' dottedName ']' slashedName { $$ = PASM->ResolveClassRef(PASM->GetAsmRef($2), $4, NULL); delete[] $2;} + | '[' mdtoken ']' slashedName { $$ = PASM->ResolveClassRef($2, $4, NULL); } + | '[' '*' ']' slashedName { $$ = PASM->ResolveClassRef(mdTokenNil, $4, NULL); } + | '[' _MODULE dottedName ']' slashedName { $$ = PASM->ResolveClassRef(PASM->GetModRef($3),$5, NULL); delete[] $3;} + | slashedName { $$ = PASM->ResolveClassRef(1,$1,NULL); } + | mdtoken { $$ = $1; } + | TYPEDEF_T { $$ = $1->m_tkTypeSpec; } + | _THIS { if(PASM->m_pCurClass != NULL) $$ = PASM->m_pCurClass->m_cl; + else { $$ = 0; PASM->report->error(".this outside class scope\n"); } + } + | _BASE { if(PASM->m_pCurClass != NULL) { + $$ = PASM->m_pCurClass->m_crExtends; + if(RidFromToken($$) == 0) + PASM->report->error(".base undefined\n"); + } else { $$ = 0; PASM->report->error(".base outside class scope\n"); } + } + | _NESTER { if(PASM->m_pCurClass != NULL) { + if(PASM->m_pCurClass->m_pEncloser != NULL) $$ = PASM->m_pCurClass->m_pEncloser->m_cl; + else { $$ = 0; PASM->report->error(".nester undefined\n"); } + } else { $$ = 0; PASM->report->error(".nester outside class scope\n"); } + } + ; + +slashedName : dottedName { $$ = $1; } + | slashedName '/' dottedName { $$ = newStringWDel($1, NESTING_SEP, $3); } + ; + +typeSpec : className { $$ = $1;} + | '[' dottedName ']' { $$ = PASM->GetAsmRef($2); delete[] $2;} + | '[' _MODULE dottedName ']' { $$ = PASM->GetModRef($3); delete[] $3;} + | type { $$ = PASM->ResolveTypeSpec($1); } + ; + +/* Native types for marshaling signatures */ +nativeType : /* EMPTY */ { $$ = new BinStr(); } + | CUSTOM_ '(' compQstring ',' compQstring ',' compQstring ',' compQstring ')' + { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_CUSTOMMARSHALER); + corEmitInt($$,$3->length()); $$->append($3); + corEmitInt($$,$5->length()); $$->append($5); + corEmitInt($$,$7->length()); $$->append($7); + corEmitInt($$,$9->length()); $$->append($9); + PASM->report->warn("Deprecated 4-string form of custom marshaler, first two strings ignored\n");} + | CUSTOM_ '(' compQstring ',' compQstring ')' + { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_CUSTOMMARSHALER); + corEmitInt($$,0); + corEmitInt($$,0); + corEmitInt($$,$3->length()); $$->append($3); + corEmitInt($$,$5->length()); $$->append($5); } + | FIXED_ SYSSTRING_ '[' int32 ']' { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_FIXEDSYSSTRING); + corEmitInt($$,$4); } + | FIXED_ ARRAY_ '[' int32 ']' nativeType + { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_FIXEDARRAY); + corEmitInt($$,$4); $$->append($6); } + | VARIANT_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_VARIANT); + PASM->report->warn("Deprecated native type 'variant'\n"); } + | CURRENCY_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_CURRENCY); } + | SYSCHAR_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_SYSCHAR); + PASM->report->warn("Deprecated native type 'syschar'\n"); } + | VOID_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_VOID); + PASM->report->warn("Deprecated native type 'void'\n"); } + | BOOL_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_BOOLEAN); } + | INT8_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_I1); } + | INT16_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_I2); } + | INT32_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_I4); } + | INT64_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_I8); } + | FLOAT32_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_R4); } + | FLOAT64_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_R8); } + | ERROR_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_ERROR); } + | UNSIGNED_ INT8_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_U1); } + | UNSIGNED_ INT16_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_U2); } + | UNSIGNED_ INT32_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_U4); } + | UNSIGNED_ INT64_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_U8); } + | UINT8_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_U1); } + | UINT16_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_U2); } + | UINT32_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_U4); } + | UINT64_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_U8); } + | nativeType '*' { $$ = $1; $$->insertInt8(NATIVE_TYPE_PTR); + PASM->report->warn("Deprecated native type '*'\n"); } + | nativeType '[' ']' { $$ = $1; if($$->length()==0) $$->appendInt8(NATIVE_TYPE_MAX); + $$->insertInt8(NATIVE_TYPE_ARRAY); } + | nativeType '[' int32 ']' { $$ = $1; if($$->length()==0) $$->appendInt8(NATIVE_TYPE_MAX); + $$->insertInt8(NATIVE_TYPE_ARRAY); + corEmitInt($$,0); + corEmitInt($$,$3); + corEmitInt($$,0); } + | nativeType '[' int32 '+' int32 ']' { $$ = $1; if($$->length()==0) $$->appendInt8(NATIVE_TYPE_MAX); + $$->insertInt8(NATIVE_TYPE_ARRAY); + corEmitInt($$,$5); + corEmitInt($$,$3); + corEmitInt($$,ntaSizeParamIndexSpecified); } + | nativeType '[' '+' int32 ']' { $$ = $1; if($$->length()==0) $$->appendInt8(NATIVE_TYPE_MAX); + $$->insertInt8(NATIVE_TYPE_ARRAY); + corEmitInt($$,$4); } + | DECIMAL_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_DECIMAL); + PASM->report->warn("Deprecated native type 'decimal'\n"); } + | DATE_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_DATE); + PASM->report->warn("Deprecated native type 'date'\n"); } + | BSTR_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_BSTR); } + | LPSTR_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_LPSTR); } + | LPWSTR_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_LPWSTR); } + | LPTSTR_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_LPTSTR); } + | OBJECTREF_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_OBJECTREF); + PASM->report->warn("Deprecated native type 'objectref'\n"); } + | IUNKNOWN_ iidParamIndex { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_IUNKNOWN); + if($2 != -1) corEmitInt($$,$2); } + | IDISPATCH_ iidParamIndex { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_IDISPATCH); + if($2 != -1) corEmitInt($$,$2); } + | STRUCT_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_STRUCT); } + | INTERFACE_ iidParamIndex { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_INTF); + if($2 != -1) corEmitInt($$,$2); } + | SAFEARRAY_ variantType { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_SAFEARRAY); + corEmitInt($$,$2); + corEmitInt($$,0);} + | SAFEARRAY_ variantType ',' compQstring { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_SAFEARRAY); + corEmitInt($$,$2); + corEmitInt($$,$4->length()); $$->append($4); } + + | INT_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_INT); } + | UNSIGNED_ INT_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_UINT); } + | UINT_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_UINT); } + | NESTED_ STRUCT_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_NESTEDSTRUCT); + PASM->report->warn("Deprecated native type 'nested struct'\n"); } + | BYVALSTR_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_BYVALSTR); } + | ANSI_ BSTR_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_ANSIBSTR); } + | TBSTR_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_TBSTR); } + | VARIANT_ BOOL_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_VARIANTBOOL); } + | METHOD_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_FUNC); } + | AS_ ANY_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_ASANY); } + | LPSTRUCT_ { $$ = new BinStr(); $$->appendInt8(NATIVE_TYPE_LPSTRUCT); } + | TYPEDEF_TS { $$ = new BinStr(); $$->append($1->m_pbsTypeSpec); } + ; + +iidParamIndex : /* EMPTY */ { $$ = -1; } + | '(' IIDPARAM_ '=' int32 ')' { $$ = $4; } + ; + +variantType : /* EMPTY */ { $$ = VT_EMPTY; } + | NULL_ { $$ = VT_NULL; } + | VARIANT_ { $$ = VT_VARIANT; } + | CURRENCY_ { $$ = VT_CY; } + | VOID_ { $$ = VT_VOID; } + | BOOL_ { $$ = VT_BOOL; } + | INT8_ { $$ = VT_I1; } + | INT16_ { $$ = VT_I2; } + | INT32_ { $$ = VT_I4; } + | INT64_ { $$ = VT_I8; } + | FLOAT32_ { $$ = VT_R4; } + | FLOAT64_ { $$ = VT_R8; } + | UNSIGNED_ INT8_ { $$ = VT_UI1; } + | UNSIGNED_ INT16_ { $$ = VT_UI2; } + | UNSIGNED_ INT32_ { $$ = VT_UI4; } + | UNSIGNED_ INT64_ { $$ = VT_UI8; } + | UINT8_ { $$ = VT_UI1; } + | UINT16_ { $$ = VT_UI2; } + | UINT32_ { $$ = VT_UI4; } + | UINT64_ { $$ = VT_UI8; } + | '*' { $$ = VT_PTR; } + | variantType '[' ']' { $$ = $1 | VT_ARRAY; } + | variantType VECTOR_ { $$ = $1 | VT_VECTOR; } + | variantType '&' { $$ = $1 | VT_BYREF; } + | DECIMAL_ { $$ = VT_DECIMAL; } + | DATE_ { $$ = VT_DATE; } + | BSTR_ { $$ = VT_BSTR; } + | LPSTR_ { $$ = VT_LPSTR; } + | LPWSTR_ { $$ = VT_LPWSTR; } + | IUNKNOWN_ { $$ = VT_UNKNOWN; } + | IDISPATCH_ { $$ = VT_DISPATCH; } + | SAFEARRAY_ { $$ = VT_SAFEARRAY; } + | INT_ { $$ = VT_INT; } + | UNSIGNED_ INT_ { $$ = VT_UINT; } + | UINT_ { $$ = VT_UINT; } + | ERROR_ { $$ = VT_ERROR; } + | HRESULT_ { $$ = VT_HRESULT; } + | CARRAY_ { $$ = VT_CARRAY; } + | USERDEFINED_ { $$ = VT_USERDEFINED; } + | RECORD_ { $$ = VT_RECORD; } + | FILETIME_ { $$ = VT_FILETIME; } + | BLOB_ { $$ = VT_BLOB; } + | STREAM_ { $$ = VT_STREAM; } + | STORAGE_ { $$ = VT_STORAGE; } + | STREAMED_OBJECT_ { $$ = VT_STREAMED_OBJECT; } + | STORED_OBJECT_ { $$ = VT_STORED_OBJECT; } + | BLOB_OBJECT_ { $$ = VT_BLOB_OBJECT; } + | CF_ { $$ = VT_CF; } + | CLSID_ { $$ = VT_CLSID; } + ; + +/* Managed types for signatures */ +type : CLASS_ className { if($2 == PASM->m_tkSysString) + { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_STRING); } + else if($2 == PASM->m_tkSysObject) + { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_OBJECT); } + else + $$ = parser->MakeTypeClass(ELEMENT_TYPE_CLASS, $2); } + | OBJECT_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_OBJECT); } + | VALUE_ CLASS_ className { $$ = parser->MakeTypeClass(ELEMENT_TYPE_VALUETYPE, $3); } + | VALUETYPE_ className { $$ = parser->MakeTypeClass(ELEMENT_TYPE_VALUETYPE, $2); } + | type '[' ']' { $$ = $1; $$->insertInt8(ELEMENT_TYPE_SZARRAY); } + | type '[' bounds1 ']' { $$ = parser->MakeTypeArray(ELEMENT_TYPE_ARRAY, $1, $3); } + | type '&' { $$ = $1; $$->insertInt8(ELEMENT_TYPE_BYREF); } + | type '*' { $$ = $1; $$->insertInt8(ELEMENT_TYPE_PTR); } + | type PINNED_ { $$ = $1; $$->insertInt8(ELEMENT_TYPE_PINNED); } + | type MODREQ_ '(' typeSpec ')' { $$ = parser->MakeTypeClass(ELEMENT_TYPE_CMOD_REQD, $4); + $$->append($1); } + | type MODOPT_ '(' typeSpec ')' { $$ = parser->MakeTypeClass(ELEMENT_TYPE_CMOD_OPT, $4); + $$->append($1); } + | methodSpec callConv type '*' '(' sigArgs0 ')' + { $$ = parser->MakeSig($2, $3, $6); + $$->insertInt8(ELEMENT_TYPE_FNPTR); + PASM->delArgNameList(PASM->m_firstArgName); + PASM->m_firstArgName = parser->m_ANSFirst.POP(); + PASM->m_lastArgName = parser->m_ANSLast.POP(); + } + | type '<' tyArgs1 '>' { if($3 == NULL) $$ = $1; + else { + $$ = new BinStr(); + $$->appendInt8(ELEMENT_TYPE_GENERICINST); + $$->append($1); + corEmitInt($$, corCountArgs($3)); + $$->append($3); delete $1; delete $3; }} + | '!' '!' int32 { //if(PASM->m_pCurMethod) { + // if(($3 < 0)||((DWORD)$3 >= PASM->m_pCurMethod->m_NumTyPars)) + // PASM->report->error("Invalid method type parameter '%d'\n",$3); + $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_MVAR); corEmitInt($$, $3); + //} else PASM->report->error("Method type parameter '%d' outside method scope\n",$3); + } + | '!' int32 { //if(PASM->m_pCurClass) { + // if(($2 < 0)||((DWORD)$2 >= PASM->m_pCurClass->m_NumTyPars)) + // PASM->report->error("Invalid type parameter '%d'\n",$2); + $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_VAR); corEmitInt($$, $2); + //} else PASM->report->error("Type parameter '%d' outside class scope\n",$2); + } + | '!' '!' dottedName { int eltype = ELEMENT_TYPE_MVAR; + int n=-1; + if(PASM->m_pCurMethod) n = PASM->m_pCurMethod->FindTyPar($3); + else { + if(PASM->m_TyParList) n = PASM->m_TyParList->IndexOf($3); + if(n == -1) + { n = TyParFixupList.COUNT(); + TyParFixupList.PUSH($3); + eltype = ELEMENT_TYPE_MVARFIXUP; + } + } + if(n == -1) { PASM->report->error("Invalid method type parameter '%s'\n",$3); + n = 0x1FFFFFFF; } + $$ = new BinStr(); $$->appendInt8(eltype); corEmitInt($$,n); + } + | '!' dottedName { int eltype = ELEMENT_TYPE_VAR; + int n=-1; + if(PASM->m_pCurClass && !newclass) n = PASM->m_pCurClass->FindTyPar($2); + else { + if(PASM->m_TyParList) n = PASM->m_TyParList->IndexOf($2); + if(n == -1) + { n = TyParFixupList.COUNT(); + TyParFixupList.PUSH($2); + eltype = ELEMENT_TYPE_VARFIXUP; + } + } + if(n == -1) { PASM->report->error("Invalid type parameter '%s'\n",$2); + n = 0x1FFFFFFF; } + $$ = new BinStr(); $$->appendInt8(eltype); corEmitInt($$,n); + } + | TYPEDREF_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_TYPEDBYREF); } + | VOID_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_VOID); } + | NATIVE_ INT_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I); } + | NATIVE_ UNSIGNED_ INT_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U); } + | NATIVE_ UINT_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U); } + | simpleType { $$ = $1; } + | ELIPSIS type { $$ = $2; $$->insertInt8(ELEMENT_TYPE_SENTINEL); } + ; + +simpleType : CHAR_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_CHAR); } + | STRING_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_STRING); } + | BOOL_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_BOOLEAN); } + | INT8_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I1); } + | INT16_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I2); } + | INT32_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I4); } + | INT64_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I8); } + | FLOAT32_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_R4); } + | FLOAT64_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_R8); } + | UNSIGNED_ INT8_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U1); } + | UNSIGNED_ INT16_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U2); } + | UNSIGNED_ INT32_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U4); } + | UNSIGNED_ INT64_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U8); } + | UINT8_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U1); } + | UINT16_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U2); } + | UINT32_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U4); } + | UINT64_ { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U8); } + | TYPEDEF_TS { $$ = new BinStr(); $$->append($1->m_pbsTypeSpec); } + ; + +bounds1 : bound { $$ = $1; } + | bounds1 ',' bound { $$ = $1; $1->append($3); delete $3; } + ; + +bound : /* EMPTY */ { $$ = new BinStr(); $$->appendInt32(0x7FFFFFFF); $$->appendInt32(0x7FFFFFFF); } + | ELIPSIS { $$ = new BinStr(); $$->appendInt32(0x7FFFFFFF); $$->appendInt32(0x7FFFFFFF); } + | int32 { $$ = new BinStr(); $$->appendInt32(0); $$->appendInt32($1); } + | int32 ELIPSIS int32 { FAIL_UNLESS($1 <= $3, ("lower bound %d must be <= upper bound %d\n", $1, $3)); + if ($1 > $3) { YYERROR; }; + $$ = new BinStr(); $$->appendInt32($1); $$->appendInt32($3-$1+1); } + | int32 ELIPSIS { $$ = new BinStr(); $$->appendInt32($1); $$->appendInt32(0x7FFFFFFF); } + ; + +/* Security declarations */ +secDecl : _PERMISSION secAction typeSpec '(' nameValPairs ')' + { PASM->AddPermissionDecl($2, $3, $5); } + | _PERMISSION secAction typeSpec '=' '{' customBlobDescr '}' + { PASM->AddPermissionDecl($2, $3, $6); } + | _PERMISSION secAction typeSpec { PASM->AddPermissionDecl($2, $3, (NVPair *)NULL); } + | psetHead bytes ')' { PASM->AddPermissionSetDecl($1, $2); } + | _PERMISSIONSET secAction compQstring + { PASM->AddPermissionSetDecl($2,BinStrToUnicode($3,true));} + | _PERMISSIONSET secAction '=' '{' secAttrSetBlob '}' + { BinStr* ret = new BinStr(); + ret->insertInt8('.'); + corEmitInt(ret, nSecAttrBlobs); + ret->append($5); + PASM->AddPermissionSetDecl($2,ret); + nSecAttrBlobs = 0; } + ; + +secAttrSetBlob : /* EMPTY */ { $$ = new BinStr(); nSecAttrBlobs = 0;} + | secAttrBlob { $$ = $1; nSecAttrBlobs = 1; } + | secAttrBlob ',' secAttrSetBlob { $$ = $1; $$->append($3); nSecAttrBlobs++; } + ; + +secAttrBlob : typeSpec '=' '{' customBlobNVPairs '}' + { $$ = PASM->EncodeSecAttr(PASM->ReflectionNotation($1),$4,nCustomBlobNVPairs); + nCustomBlobNVPairs = 0; } + | CLASS_ SQSTRING '=' '{' customBlobNVPairs '}' + { $$ = PASM->EncodeSecAttr($2,$5,nCustomBlobNVPairs); + nCustomBlobNVPairs = 0; } + ; + +psetHead : _PERMISSIONSET secAction '=' '(' { $$ = $2; bParsingByteArray = TRUE; } + | _PERMISSIONSET secAction BYTEARRAY_ '(' + { $$ = $2; bParsingByteArray = TRUE; } + ; + +nameValPairs : nameValPair { $$ = $1; } + | nameValPair ',' nameValPairs { $$ = $1->Concat($3); } + ; + +nameValPair : compQstring '=' caValue { $1->appendInt8(0); $$ = new NVPair($1, $3); } + ; + +truefalse : TRUE_ { $$ = 1; } + | FALSE_ { $$ = 0; } + ; + +caValue : truefalse { $$ = new BinStr(); + $$->appendInt8(SERIALIZATION_TYPE_BOOLEAN); + $$->appendInt8($1); } + | int32 { $$ = new BinStr(); + $$->appendInt8(SERIALIZATION_TYPE_I4); + $$->appendInt32($1); } + | INT32_ '(' int32 ')' { $$ = new BinStr(); + $$->appendInt8(SERIALIZATION_TYPE_I4); + $$->appendInt32($3); } + | compQstring { $$ = new BinStr(); + $$->appendInt8(SERIALIZATION_TYPE_STRING); + $$->append($1); delete $1; + $$->appendInt8(0); } + | className '(' INT8_ ':' int32 ')' { $$ = new BinStr(); + $$->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation($1); + strcpy_s((char *)$$->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + $$->appendInt8(1); + $$->appendInt32($5); } + | className '(' INT16_ ':' int32 ')' { $$ = new BinStr(); + $$->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation($1); + strcpy_s((char *)$$->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + $$->appendInt8(2); + $$->appendInt32($5); } + | className '(' INT32_ ':' int32 ')' { $$ = new BinStr(); + $$->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation($1); + strcpy_s((char *)$$->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + $$->appendInt8(4); + $$->appendInt32($5); } + | className '(' int32 ')' { $$ = new BinStr(); + $$->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation($1); + strcpy_s((char *)$$->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + $$->appendInt8(4); + $$->appendInt32($3); } + ; + +secAction : REQUEST_ { $$ = dclRequest; } + | DEMAND_ { $$ = dclDemand; } + | ASSERT_ { $$ = dclAssert; } + | DENY_ { $$ = dclDeny; } + | PERMITONLY_ { $$ = dclPermitOnly; } + | LINKCHECK_ { $$ = dclLinktimeCheck; } + | INHERITCHECK_ { $$ = dclInheritanceCheck; } + | REQMIN_ { $$ = dclRequestMinimum; } + | REQOPT_ { $$ = dclRequestOptional; } + | REQREFUSE_ { $$ = dclRequestRefuse; } + | PREJITGRANT_ { $$ = dclPrejitGrant; } + | PREJITDENY_ { $$ = dclPrejitDenied; } + | NONCASDEMAND_ { $$ = dclNonCasDemand; } + | NONCASLINKDEMAND_ { $$ = dclNonCasLinkDemand; } + | NONCASINHERITANCE_ { $$ = dclNonCasInheritance; } + ; + +/* External source declarations */ +esHead : _LINE { PASM->ResetLineNumbers(); nCurrPC = PASM->m_CurPC; PENV->bExternSource = TRUE; PENV->bExternSourceAutoincrement = FALSE; } + | P_LINE { PASM->ResetLineNumbers(); nCurrPC = PASM->m_CurPC; PENV->bExternSource = TRUE; PENV->bExternSourceAutoincrement = TRUE; } + ; + +extSourceSpec : esHead int32 SQSTRING { PENV->nExtLine = PENV->nExtLineEnd = $2; + PENV->nExtCol = 0; PENV->nExtColEnd = static_cast<unsigned>(-1); + PASM->SetSourceFileName($3);} + | esHead int32 { PENV->nExtLine = PENV->nExtLineEnd = $2; + PENV->nExtCol = 0; PENV->nExtColEnd = static_cast<unsigned>(-1); } + | esHead int32 ':' int32 SQSTRING { PENV->nExtLine = PENV->nExtLineEnd = $2; + PENV->nExtCol=$4; PENV->nExtColEnd = static_cast<unsigned>(-1); + PASM->SetSourceFileName($5);} + | esHead int32 ':' int32 { PENV->nExtLine = PENV->nExtLineEnd = $2; + PENV->nExtCol=$4; PENV->nExtColEnd = static_cast<unsigned>(-1);} + | esHead int32 ':' int32 ',' int32 SQSTRING + { PENV->nExtLine = PENV->nExtLineEnd = $2; + PENV->nExtCol=$4; PENV->nExtColEnd = $6; + PASM->SetSourceFileName($7);} + | esHead int32 ':' int32 ',' int32 + { PENV->nExtLine = PENV->nExtLineEnd = $2; + PENV->nExtCol=$4; PENV->nExtColEnd = $6; } + | esHead int32 ',' int32 ':' int32 SQSTRING + { PENV->nExtLine = $2; PENV->nExtLineEnd = $4; + PENV->nExtCol=$6; PENV->nExtColEnd = static_cast<unsigned>(-1); + PASM->SetSourceFileName($7);} + | esHead int32 ',' int32 ':' int32 + { PENV->nExtLine = $2; PENV->nExtLineEnd = $4; + PENV->nExtCol=$6; PENV->nExtColEnd = static_cast<unsigned>(-1); } + | esHead int32 ',' int32 ':' int32 ',' int32 SQSTRING + { PENV->nExtLine = $2; PENV->nExtLineEnd = $4; + PENV->nExtCol=$6; PENV->nExtColEnd = $8; + PASM->SetSourceFileName($9);} + | esHead int32 ',' int32 ':' int32 ',' int32 + { PENV->nExtLine = $2; PENV->nExtLineEnd = $4; + PENV->nExtCol=$6; PENV->nExtColEnd = $8; } + | esHead int32 QSTRING { PENV->nExtLine = PENV->nExtLineEnd = $2 - 1; + PENV->nExtCol = 0; PENV->nExtColEnd = static_cast<unsigned>(-1); + PASM->SetSourceFileName($3);} + ; + +/* Manifest declarations */ +fileDecl : _FILE fileAttr dottedName fileEntry hashHead bytes ')' fileEntry + { PASMM->AddFile($3, $2|$4|$8, $6); } + | _FILE fileAttr dottedName fileEntry { PASMM->AddFile($3, $2|$4, NULL); } + ; + +fileAttr : /* EMPTY */ { $$ = (CorFileFlags) 0; } + | fileAttr NOMETADATA_ { $$ = (CorFileFlags) ($1 | ffContainsNoMetaData); } + ; + +fileEntry : /* EMPTY */ { $$ = (CorFileFlags) 0; } + | _ENTRYPOINT { $$ = (CorFileFlags) 0x80000000; } + ; + +hashHead : _HASH '=' '(' { bParsingByteArray = TRUE; } + ; + +assemblyHead : _ASSEMBLY asmAttr dottedName { PASMM->StartAssembly($3, NULL, (DWORD)$2, FALSE); } + ; + +asmAttr : /* EMPTY */ { $$ = (CorAssemblyFlags) 0; } + | asmAttr RETARGETABLE_ { $$ = (CorAssemblyFlags) ($1 | afRetargetable); } + | asmAttr WINDOWSRUNTIME_ { $$ = (CorAssemblyFlags) ($1 | afContentType_WindowsRuntime); } + | asmAttr NOPLATFORM_ { $$ = (CorAssemblyFlags) ($1 | afPA_NoPlatform); } + | asmAttr LEGACY_ LIBRARY_ { $$ = $1; } + | asmAttr CIL_ { SET_PA($$,$1,afPA_MSIL); } + | asmAttr X86_ { SET_PA($$,$1,afPA_x86); } + | asmAttr IA64_ { SET_PA($$,$1,afPA_IA64); } + | asmAttr AMD64_ { SET_PA($$,$1,afPA_AMD64); } + | asmAttr ARM_ { SET_PA($$,$1,afPA_ARM); } + ; + +assemblyDecls : /* EMPTY */ + | assemblyDecls assemblyDecl + ; + +assemblyDecl : _HASH ALGORITHM_ int32 { PASMM->SetAssemblyHashAlg($3); } + | secDecl + | asmOrRefDecl + ; + +intOrWildcard : int32 { $$ = $1; } + | '*' { $$ = 0xFFFF; } + ; + +asmOrRefDecl : publicKeyHead bytes ')' { PASMM->SetAssemblyPublicKey($2); } + | _VER intOrWildcard ':' intOrWildcard ':' intOrWildcard ':' intOrWildcard + { PASMM->SetAssemblyVer((USHORT)$2, (USHORT)$4, (USHORT)$6, (USHORT)$8); } + | _LOCALE compQstring { $2->appendInt8(0); PASMM->SetAssemblyLocale($2,TRUE); } + | localeHead bytes ')' { PASMM->SetAssemblyLocale($2,FALSE); } + | customAttrDecl + | compControl + ; + +publicKeyHead : _PUBLICKEY '=' '(' { bParsingByteArray = TRUE; } + ; + +publicKeyTokenHead : _PUBLICKEYTOKEN '=' '(' { bParsingByteArray = TRUE; } + ; + +localeHead : _LOCALE '=' '(' { bParsingByteArray = TRUE; } + ; + +assemblyRefHead : _ASSEMBLY EXTERN_ asmAttr dottedName + { PASMM->StartAssembly($4, NULL, $3, TRUE); } + | _ASSEMBLY EXTERN_ asmAttr dottedName AS_ dottedName + { PASMM->StartAssembly($4, $6, $3, TRUE); } + ; + +assemblyRefDecls : /* EMPTY */ + | assemblyRefDecls assemblyRefDecl + ; + +assemblyRefDecl : hashHead bytes ')' { PASMM->SetAssemblyHashBlob($2); } + | asmOrRefDecl + | publicKeyTokenHead bytes ')' { PASMM->SetAssemblyPublicKeyToken($2); } + | AUTO_ { PASMM->SetAssemblyAutodetect(); } + ; + +exptypeHead : _CLASS EXTERN_ exptAttr dottedName { PASMM->StartComType($4, $3);} + ; + +exportHead : _EXPORT exptAttr dottedName /* deprecated */ { PASMM->StartComType($3, $2); } + ; + +exptAttr : /* EMPTY */ { $$ = (CorTypeAttr) 0; } + | exptAttr PRIVATE_ { $$ = (CorTypeAttr) ($1 | tdNotPublic); } + | exptAttr PUBLIC_ { $$ = (CorTypeAttr) ($1 | tdPublic); } + | exptAttr FORWARDER_ { $$ = (CorTypeAttr) ($1 | tdForwarder); } + | exptAttr NESTED_ PUBLIC_ { $$ = (CorTypeAttr) ($1 | tdNestedPublic); } + | exptAttr NESTED_ PRIVATE_ { $$ = (CorTypeAttr) ($1 | tdNestedPrivate); } + | exptAttr NESTED_ FAMILY_ { $$ = (CorTypeAttr) ($1 | tdNestedFamily); } + | exptAttr NESTED_ ASSEMBLY_ { $$ = (CorTypeAttr) ($1 | tdNestedAssembly); } + | exptAttr NESTED_ FAMANDASSEM_ { $$ = (CorTypeAttr) ($1 | tdNestedFamANDAssem); } + | exptAttr NESTED_ FAMORASSEM_ { $$ = (CorTypeAttr) ($1 | tdNestedFamORAssem); } + ; + +exptypeDecls : /* EMPTY */ + | exptypeDecls exptypeDecl + ; + +exptypeDecl : _FILE dottedName { PASMM->SetComTypeFile($2); } + | _CLASS EXTERN_ slashedName { PASMM->SetComTypeComType($3); } + | _ASSEMBLY EXTERN_ dottedName { PASMM->SetComTypeAsmRef($3); } + | MDTOKEN_ '(' int32 ')' { if(!PASMM->SetComTypeImplementationTok($3)) + PASM->report->error("Invalid implementation of exported type\n"); } + | _CLASS int32 { if(!PASMM->SetComTypeClassTok($2)) + PASM->report->error("Invalid TypeDefID of exported type\n"); } + | customAttrDecl + | compControl + ; + +manifestResHead : _MRESOURCE manresAttr dottedName { PASMM->StartManifestRes($3, $3, $2); } + | _MRESOURCE manresAttr dottedName AS_ dottedName + { PASMM->StartManifestRes($3, $5, $2); } + ; + +manresAttr : /* EMPTY */ { $$ = (CorManifestResourceFlags) 0; } + | manresAttr PUBLIC_ { $$ = (CorManifestResourceFlags) ($1 | mrPublic); } + | manresAttr PRIVATE_ { $$ = (CorManifestResourceFlags) ($1 | mrPrivate); } + ; + +manifestResDecls : /* EMPTY */ + | manifestResDecls manifestResDecl + ; + +manifestResDecl : _FILE dottedName AT_ int32 { PASMM->SetManifestResFile($2, (ULONG)$4); } + | _ASSEMBLY EXTERN_ dottedName { PASMM->SetManifestResAsmRef($3); } + | customAttrDecl + | compControl + ; + + +%% + +#include "grammar_after.cpp" |