Leaked source code of windows server 2003
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.
 
 
 
 
 
 

9190 lines
329 KiB

extern BOOL gbWin16Mode;
UINT CPDLParser::CountTags ( TokenDescriptor *tokdesc )
{
UINT uCount;
TagDescriptor *pTagDescriptor;
for ( uCount = 0, pTagDescriptor = tokdesc -> Tags ; pTagDescriptor -> szTag != NULL;
uCount++, pTagDescriptor++ );
return uCount;
}
CPDLParser::CPDLParser()
{
fpHComPlusFile = NULL;
fpCComPlusFile = NULL;
fpHDLFile = NULL;
fpHeaderFile = NULL;
fpIDLFile = NULL;
fpLOGFile = NULL;
fpHTMFile = NULL;
fpHTMIndexFile = NULL;
fpDISPIDFile = NULL;
fpMaxLenFile = NULL;
pRuntimeList = new CTokenList;
pDynamicTypeList = new CTokenList;
pDynamicEventTypeList = new CTokenList;
Init();
}
void
CPDLParser::SplitTag ( char *pStr, int nLen, char **pTag, int *pnTagLen,
char **pValue, int *pnValueLen )
{
*pTag = pStr;
for ( *pnTagLen = 0 ; *pnTagLen < nLen ; pStr++, (*pnTagLen)++ )
{
if ( *pStr == ':' )
{
*pValue = pStr + 1;
*pnValueLen = nLen - *pnTagLen -1;
return;
}
}
*pnValueLen = 0;
}
BOOL
CPDLParser::LookupToken ( LPCSTR pTokenName, int nTokenLen,
TokenDescriptor **ppTokenDescriptor, DESCRIPTOR_TYPE *pnTokenDes )
{
INT i;
for ( i = 0 ;
i < NUM_DESCRIPTOR_TYPES ; i++ )
{
if (strlen(AllDescriptors[i]->szTokenName) == (UINT)nTokenLen &&
!_strnicmp(AllDescriptors[i]->szTokenName, pTokenName, nTokenLen))
{
*ppTokenDescriptor = AllDescriptors [ i ];
*pnTokenDes = (DESCRIPTOR_TYPE)i;
return TRUE;
}
}
return FALSE;
}
BOOL CPDLParser::GetElem ( char **pStr,
char **pElem,
int *pnLen,
BOOL fBreakOnOpenParenthesis, /* = FALSE */
BOOL fBreakOnCloseParenthesis, /* = FALSE */
BOOL fBreakOnCommas /* = FALSE */ )
{
*pnLen = 0;
while ( isspace ( **pStr ) )
{
(*pStr)++;
}
*pElem = *pStr;
if (( fBreakOnOpenParenthesis && **pStr == ')' ) ||
( fBreakOnCloseParenthesis && **pStr == '(' ) ||
(fBreakOnCommas && **pStr == ',' ))
{
(*pnLen)++;
(*pStr)++;
goto Cleanup;
}
while ( **pStr && !isspace ( **pStr ))
{
if (( fBreakOnOpenParenthesis && **pStr == ')' ) ||
( fBreakOnCloseParenthesis && **pStr == '(' ) ||
(fBreakOnCommas && **pStr == ',' ))
{
// Break but leave the pStr pointing at the bracket - we'll pick it up in the
// next call
break;
}
// Convert curly braces to parens
if (**pStr == '{')
**pStr = '(';
else if (**pStr == '}')
**pStr = ')';
(*pnLen)++;
(*pStr)++;
}
Cleanup:
return *pnLen == 0 ? FALSE : TRUE;
}
BOOL CPDLParser::ParseInputFile ( BOOL fDebugging )
{
BOOL fReturn = TRUE;
DESCRIPTOR_TYPE nThisDescriptor;
char szLineBuffer [ MAX_LINE_LEN+1 ];
char szErrorText [ MAX_LINE_LEN+1 ];
char *pStr = szLineBuffer;
char *pElem; int nElemLen;
TokenDescriptor *pThisDescriptor;
Token *pNewToken;
Token *pParentToken = NULL;
BOOL fGotParentToken = FALSE;
CString szType;
fprintf ( fpLOGFile, "Parsing input file\n" );
for(;;)
{
if ( !GetStdInLine ( szLineBuffer, sizeof ( szLineBuffer ) ) )
break;
pStr = szLineBuffer;
fprintf ( fpLOGFile, "Read Line:%s\n", szLineBuffer );
// Get the type e..g. enum, eval etc.
if ( !GetElem ( &pStr, &pElem, &nElemLen ) )
{
// Couldn't get the name
fprintf ( fpLOGFile, "Skipping\n" );
continue;
}
if ( !LookupToken ( pElem, nElemLen, &pThisDescriptor, &nThisDescriptor ) )
{
fprintf ( fpLOGFile, "Unknown token\n" );
continue;
}
fprintf ( fpLOGFile, "Processing a %s declaration\n",
(LPCSTR)AllDescriptors [ nThisDescriptor ] -> szTokenName );
// If it's a child token and we haven't got a parent
if ( !pThisDescriptor->fIsParentToken &&
!fGotParentToken )
{
ReportError ( "Child Token Without Parent\n" );
goto error;
}
if ( pThisDescriptor->fIsParentToken )
{
fGotParentToken = TRUE;
}
INT nTag;
char *pTag; char *pValue;
int nTagLen; int nValueLen;
BOOL fVarArg = FALSE;
if ( nThisDescriptor == TYPE_METHOD )
{
// Look for optional vararg first
if ( !GetElem ( &pStr, &pElem, &nElemLen ) )
{
// Couldn't get the return type
continue;
}
if ( ! ( pNewToken = pParentToken -> AddChildToken ( nThisDescriptor ) ) )
{
ReportError ( "Memory Allocation Error\n" );
goto error;
}
if ( !pNewToken->TagValues.AddTag ( METHOD_RETURNTYPE, pElem, nElemLen ) )
{
ReportError ( "Memory Allocation Error\n" );
goto error;
}
// Name is next
if ( !GetElem ( &pStr, &pElem, &nElemLen ) )
{
// Couldn't get the name
continue;
}
if ( !pNewToken->TagValues.AddTag ( METHOD_NAME, pElem, nElemLen ) )
{
ReportError ( "Memory Allocation Error\n" );
goto error;
}
// Methods need special handling due to the parameter list
// Put all tokens before the "(" in the TagValues
// Treat each arg in the param list as a unique token and add
// to the pArgList for this token
// Put all the tokens after the ")" in the TagValues
// We allow either a comma-seperated arg list, but if we
// don't get commas we break the arg intelligently
//
UINT bInParams = FALSE;
BOOL bCreatedArgToken = FALSE;
Token *pCurrentToken;
TokenDescriptor *pDescriptor = pThisDescriptor;
pCurrentToken = pNewToken;
fVarArg = FALSE;
// Set the fBreakOnParenthesis Flag to make parenthis stop GetElem
while ( GetElem ( &pStr, &pElem, &nElemLen, TRUE, TRUE, TRUE ) )
{
if ( nElemLen == 1 && *pElem == '(' )
{
if ( bInParams )
{
sprintf ( szErrorText, "Syntax Error %s On %s\n", pStr, szLineBuffer );
ReportError ( szErrorText );
goto error;
}
bInParams = TRUE;
// Switch to method arg descriptor
pDescriptor = &MethodArgDescriptor;
}
else if ( nElemLen == 1 && *pElem == ')' )
{
if ( !bInParams )
{
sprintf ( szErrorText, "Syntax Error %s On %s\n", pStr, szLineBuffer );
ReportError ( szErrorText );
goto error;
}
bInParams = FALSE;
// Switch back to method descriptor
pDescriptor = pThisDescriptor;
pCurrentToken = pNewToken;
}
else if ( nElemLen == 1 && *pElem == ',' )
{
// Reset flag so new arg token gets created for next arg
bCreatedArgToken = FALSE;
}
else
{
// Split out the prefix:value
SplitTag ( pElem, nElemLen, &pTag, &nTagLen,
&pValue, &nValueLen );
// Match the tag
if ( !pDescriptor->LookupTagName ( pTag, nTagLen, &nTag ) )
{
pTag [ nTagLen ] = '\0';
sprintf ( szErrorText, "Unknown tag: %s On %s\n", pTag, szLineBuffer );
ReportError ( szErrorText );
goto error;
}
// If we've already got an entry for this tag, and we've seen
// at least the arg tag, start a new arg
if ( bInParams && pCurrentToken -> IsSet ( METHODARG_ARGNAME ) &&
( nTag == METHODARG_IN || nTag == METHODARG_OUT ) &&
( pCurrentToken -> IsSet ( METHODARG_IN ) ||
pCurrentToken -> IsSet ( METHODARG_IN ) ) )
{
// Start a new arg
bCreatedArgToken = FALSE;
}
if ( bInParams && bCreatedArgToken == FALSE )
{
// Create the arg list if needed
pCurrentToken = pNewToken -> AddChildToken ( TYPE_METHOD_ARG );
if ( pCurrentToken == NULL )
{
ReportError ( "Memory allocation error\n" );
goto error;
}
bCreatedArgToken = TRUE;
}
// Add the tag either to the main method token array or to the current
// arg 's array
if ( !pCurrentToken->TagValues.AddTag ( nTag, pValue, nValueLen ) )
{
ReportError ( "Memory allocation error\n" );
goto error;
}
// Last argument a SAFEARRAY, if so then vararg
fVarArg = (strncmp(pValue, "SAFEARRAY(VARIANT)", 18) == 0);
}
// method is a vararg because last parameter is a safearray.
if ( fVarArg && !pNewToken->TagValues.AddTag ( METHOD_VARARG, "vararg", 6 ) )
{
ReportError ( "Memory allocation error\n" );
goto error;
}
}
}
else if ( nThisDescriptor == TYPE_REFPROP || nThisDescriptor == TYPE_REFMETHOD )
{
// Now get the Class::Name & split it out
if ( !GetElem ( &pStr, &pElem, &nElemLen ) )
{
// Couldn't get the name
continue;
}
// Split out the prefix:value
SplitTag ( pElem, nElemLen, &pTag, &nTagLen,
&pValue, &nValueLen );
pNewToken = pParentToken -> AddChildToken ( nThisDescriptor );
if ( pNewToken == NULL )
{
ReportError ( "Memory Allocation Error\n" );
goto error;
}
if ( !pNewToken->TagValues.AddTag (
(nThisDescriptor == TYPE_REFPROP) ? (INT)REFPROP_CLASSNAME : (INT)REFMETHOD_CLASSNAME,
pTag, nTagLen ) )
{
ReportError ( "Memory Allocation Error\n" );
goto error;
}
if ( !pNewToken->TagValues.AddTag (
nThisDescriptor == TYPE_REFPROP ? (INT)REFPROP_PROPERTYNAME : (INT)REFMETHOD_METHODNAME,
pValue, nValueLen ) )
{
ReportError ( "Memory Allocation Error\n" );
goto error;
}
}
else
{
// Now get the name
if ( !GetElem ( &pStr, &pElem, &nElemLen ) )
{
// Couldn't get the name
continue;
}
// If it's a child token, add it to the runtime list, else add it as a child
// of the current parent
if ( pThisDescriptor->fIsParentToken )
{
pNewToken = pRuntimeList -> AddNewToken ( nThisDescriptor );
pParentToken = pNewToken;
}
else
{
pNewToken = pParentToken -> AddChildToken ( nThisDescriptor );
}
if ( pNewToken == NULL )
{
ReportError ( "Memory Allocation Error\n" );
goto error;
}
// First tag is always the name
if ( !pNewToken->TagValues.AddTag ( NAME_TAG, pElem, nElemLen ) )
{
ReportError ( "Memory Allocation Error\n" );
goto error;
}
// Split out all the token:value pairs
while ( GetElem ( &pStr, &pElem, &nElemLen ) )
{
// Split out the prefix:value
SplitTag ( pElem, nElemLen, &pTag, &nTagLen,
&pValue, &nValueLen );
// Match the tag
if ( !pThisDescriptor->LookupTagName ( pTag, nTagLen, &nTag ) )
{
pTag [ nTagLen ] = '\0';
sprintf ( szErrorText, "Unknown tag: %s On %s\n", pTag, szLineBuffer );
ReportError ( szErrorText );
goto error;
}
if ( !pNewToken->TagValues.AddTag ( nTag, pValue, nValueLen ) )
{
ReportError ( "Memory Allocation Error\n" );
goto error;
}
}
}
// Perform any cleanup
switch ( nThisDescriptor )
{
case TYPE_EVAL:
// For enums we calculate and store in the token the enum mask
// We also number the enum values sequentialy
pNewToken -> CalculateEnumMask ( pParentToken );
break;
case TYPE_ENUM:
// Add data types to the dynamic type array
szType = pNewToken -> GetTagValue ( ENUM_NAME );
AddType ( szType, "Enum" );
AddEventType ( szType, "VTS_I4" );
szType += "*";
AddEventType ( szType, "VTS_PI4" );
break;
case TYPE_CLASS:
case TYPE_INTERFACE:
case TYPE_EVENT:
szType = pNewToken -> GetTagValue ( NAME_TAG );
szType += "*";
AddType ( szType, "object" );
AddEventType ( szType, "VTS_DISPATCH" );
szType += "*";
AddType ( szType, "object" );
AddEventType ( szType, "VTS_DISPATCH" );
break;
}
}
// Add an IUnknown to make implicit ref's match up
pNewToken = pRuntimeList -> AddNewToken ( TYPE_INTERFACE );
pNewToken->TagValues.AddTag ( INTERFACE_NAME, "IUnknown", -1 );
// Add an IDispatch to make implicit ref's match up
pNewToken = pRuntimeList -> AddNewToken ( TYPE_INTERFACE );
pNewToken->TagValues.AddTag ( INTERFACE_NAME, "IDispatch", -1 );
pNewToken = pRuntimeList -> AddNewToken ( TYPE_EVENT );
pNewToken->TagValues.AddTag ( EVENT_NAME, "IDispatch", -1 );
// Patch up the refprops & refmethods
if ( !PatchInterfaceRefTypes() )
{
goto error;
}
// Patch Properties that are of object type
if ( !PatchPropertyTypes() )
{
goto error;
}
if ( !PatchInterfaces() )
{
goto error;
}
goto cleanup;
error:
fReturn = FALSE;
cleanup:
return fReturn;
}
BOOL CPDLParser::PatchInterfaceRefTypes ( void )
{
CTokenListWalker WholeTree ( pRuntimeList );
Token *pChildToken;
Token *pInterfaceToken;
CString szClassName;
// For each RefProp or Refmethod, we replace the arg list with a copy of the referenced property/method
// and change the type of the ref'd item appropriatly
while ( pInterfaceToken = WholeTree.GetNext( TYPE_INTERFACE ) )
{
CTokenListWalker ChildList ( pInterfaceToken );
while ( pChildToken = ChildList.GetNext() )
{
if ( pChildToken -> GetType() == TYPE_REFPROP )
{
szClassName = pChildToken -> GetTagValue ( REFPROP_CLASSNAME );
if ( !CloneToken ( pChildToken, TYPE_PROPERTY,
REFPROP_CLASSNAME, REFPROP_PROPERTYNAME ) )
{
char szErrorText [ MAX_LINE_LEN+1 ];
sprintf ( szErrorText, "Interface %s Invalid RefProp %s:%s\n" ,
pInterfaceToken -> GetTagValue ( INTERFACE_NAME ),
pChildToken -> GetTagValue ( REFPROP_CLASSNAME ),
pChildToken -> GetTagValue ( REFPROP_PROPERTYNAME ) );
ReportError ( szErrorText );
return FALSE;
}
// Remember the class that was refprop'd.
pChildToken -> AddTag ( PROPERTY_REFDTOCLASS, (LPCSTR)szClassName );
}
else if ( pChildToken -> GetType() == TYPE_REFMETHOD )
{
szClassName = pChildToken -> GetTagValue ( REFMETHOD_CLASSNAME );
if ( !CloneToken ( pChildToken, TYPE_METHOD,
REFMETHOD_CLASSNAME, REFMETHOD_METHODNAME ) )
{
char szErrorText [ MAX_LINE_LEN+1 ];
sprintf ( szErrorText, "Interface %s Invalid RefMethod %s:%s\n" ,
pInterfaceToken -> GetTagValue ( INTERFACE_NAME ),
pChildToken -> GetTagValue ( REFMETHOD_CLASSNAME ),
pChildToken -> GetTagValue ( REFMETHOD_METHODNAME ) );
ReportError ( szErrorText );
return FALSE;
}
// Remember the class that was refprop'd.
pChildToken -> AddTag ( METHOD_REFDTOCLASS, (LPCSTR)szClassName );
}
}
}
return TRUE;
}
BOOL CPDLParser::CloneToken ( Token *pChildToken, DESCRIPTOR_TYPE Type, INT nClassName, INT nTagName )
{
CTokenListWalker SubTree ( pRuntimeList );
Token *pRefdClassToken;
Token *pRefdChild;
pRefdClassToken = SubTree.GetNext( TYPE_CLASS, pChildToken -> GetTagValue ( nClassName ) );
if ( pRefdClassToken == NULL )
{
// Couldn't find the refd class
return FALSE;
}
// Found the refd class, find the refd property
CTokenListWalker RefdChildList ( pRefdClassToken );
pRefdChild = RefdChildList.GetNext ( Type,
pChildToken -> GetTagValue ( nTagName ) );
if ( pRefdChild == NULL )
{
// Couldn't find the refd property
return FALSE;
}
else
{
pChildToken -> Clone ( pRefdChild );
}
return TRUE;
}
BOOL CPDLParser::GetTypeDetails ( char *szTypeName, CString& szHandler, CString &szFnPrefix,
StorageType *pStorageType /* = NULL */ )
{
if ( !LookupType ( szTypeName, szHandler, szFnPrefix, pStorageType ) )
return FALSE;
return TRUE;
}
BOOL CPDLParser::IsSpecialProperty(Token *pClassToken)
{
CString szInterf;
Token *pInterf;
szInterf = pClassToken->GetTagValue(CLASS_INTERFACE);
pInterf = FindInterface(szInterf);
if (pInterf)
return (PrimaryTearoff(pInterf) || pInterf->IsSet(INTERFACE_ABSTRACT));
else
return TRUE;
}
BOOL CPDLParser::GeneratePropMethodImplementation ( void )
{
Token *pClassToken;
Token *pChildToken;
CString szFnPrefix;
CString szHandler;
CString szOffsetOf;
CString szAType;
CString szHandlerArgs;
char szErrorText [ MAX_LINE_LEN+1 ];
// Only generate def's for this file
CTokenListWalker TokenList ( pRuntimeList, _pszPDLFileName );
// Generate propdescs for every property token in every class ( in this file )
while ( pClassToken = TokenList.GetNext( TYPE_CLASS ) )
{
if (!IsSpecialProperty(pClassToken))
{
fprintf ( fpHDLFile, "\n// Property get/set method implementation for class %s\n", (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ) );
fprintf ( fpHDLFile, "\n" );
CTokenListWalker ChildList ( pClassToken );
while ( pChildToken = ChildList.GetNext() )
{
if ( pChildToken->nType == TYPE_METHOD ||
pChildToken->nType == TYPE_IMPLEMENTS ||
pChildToken -> IsSet ( PROPERTY_ABSTRACT ) ||
pChildToken -> IsSet ( PROPERTY_BASEIMPLEMENTATION ) )
{
continue;
}
// If propdesc for nameOnly then we wont need a handler for this property
// another property that matches this will do the handling.
if ( _stricmp(pChildToken->GetTagValue(PROPERTY_NOPROPDESC), "nameonly") == 0 )
continue;
if ( !GetTypeDetails ( pChildToken->GetTagValue ( PROPERTY_TYPE ),
szHandler, szFnPrefix ) )
{
sprintf ( szErrorText ,"Invalid Type:%s in Class:%s Property:%s\n",
(LPCSTR)pChildToken->GetTagValue ( PROPERTY_TYPE ),
(LPCSTR)pClassToken->GetTagValue(CLASS_NAME),
(LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ) );
ReportError ( szErrorText );
return FALSE;
}
if ( pChildToken -> IsSet ( PROPERTY_CAA ) )
{
szOffsetOf = "(GetAttrArray())";
}
else
{
szOffsetOf = "(this)";
}
szAType = pChildToken->GetTagValue ( PROPERTY_ATYPE );
// Generate set implementation
if ( pChildToken -> IsSet ( PROPERTY_SET ) )
{
szHandlerArgs = "HANDLEPROP_SET | HANDLEPROP_AUTOMATION | (PROPTYPE_VARIANT << 16)";
GenerateMethodImp ( pClassToken, pChildToken, TRUE,
szHandler, szHandlerArgs, szOffsetOf, szAType );
}
// Generate Get implementation
if ( pChildToken -> IsSet ( PROPERTY_GET ) )
{
szHandlerArgs = "HANDLEPROP_AUTOMATION | (PROPTYPE_VARIANT << 16)";
GenerateMethodImp ( pClassToken, pChildToken, FALSE,
szHandler, szHandlerArgs, szOffsetOf, szAType );
}
}
}
fprintf ( fpHDLFile, "\n" );
// Whip thru all tearoffs.
Token *pLastTearoff = NULL;
BOOL fMostDerivedOnly;
while ((pLastTearoff = NextTearoff((LPCSTR)pClassToken->GetTagValue(CLASS_NAME), pLastTearoff)))
{
LPSTR szInterface = (LPSTR)pLastTearoff->GetTagValue(TEAROFF_INTERFACE);
// If the tearoff is the primary interface of the coclass then we'll
// not stack the derived interfaces but generate separate
fMostDerivedOnly = (_stricmp(szInterface, (LPSTR)pClassToken->GetTagValue(CLASS_INTERFACE)) == 0 &&
_stricmp(szInterface, "IHTMLDocument2"));
if ( !GenerateTearoffTable(pClassToken, pLastTearoff, szInterface, fMostDerivedOnly))
return FALSE;
}
}
return TRUE;
}
BOOL CPDLParser::FindTearoffMethod(Token *pTearoff, LPCSTR pszTearoffMethod, LPSTR pszUseTearoff)
{
Token *pChildToken;
CTokenListWalker ChildList(pTearoff);
while (pChildToken = ChildList.GetNext())
{
if (pChildToken->GetType() == TYPE_TEAROFFMETHOD)
{
if (strcmp((LPCSTR)pChildToken->GetTagValue(TEAROFFMETHOD_NAME),
pszTearoffMethod) == 0)
{
// Check if there is a class name in the method, if it is then
// extract it explicity.
strcpy(pszUseTearoff, (LPCSTR)pChildToken->GetTagValue(TEAROFFMETHOD_MAPTO));
return TRUE;
}
}
}
// Call the super:: implementation except for the primary tearoff the base
// implementation of each method if not specified is the current class.
strcpy(pszUseTearoff, pTearoff->IsSet(TEAROFF_BASEIMPL) ?
(LPCSTR)pTearoff->GetTagValue(TEAROFF_BASEIMPL) : "");
strcat(pszUseTearoff, pszTearoffMethod);
return FALSE;
}
// We exploit the Linker's Case insensitive feature to do Tearoffs in Win16.
// This function takes a Tearoff Method and generates a name that is different
// in case from the Real Tearoff Method. We have to follow certain rules so that
// the compiler doesn't complain about undefined symbols and the linker puts in
// the correct address anyhow.
void GenerateWin16TearoffName(LPSTR szWin16Name, LPSTR pszTearoffMethod, LPSTR szClassName = NULL)
{
strcpy(szWin16Name, pszTearoffMethod);
// if the Tearoff has a put_ or get_ prefix then we capitalize the PUT_
// or GET_
if ( !strncmp(szWin16Name, "put_", 4) )
{
strncpy(szWin16Name, "PUT_", 4);
return;
}
if ( !strncmp(szWin16Name, "get_", 4) )
{
strncpy(szWin16Name, "GET_", 4);
return;
}
// Check if there is a class name in the method, if it is super
// then let it be else extract that and copy it to szClassName.
char *p = strstr(szWin16Name, "::");
if ( p && strncmp(szWin16Name, "super::",7) )
{
strcpy(pszTearoffMethod, p+2);
if ( szClassName )
{
*p = '\0';
strcpy(szClassName, szWin16Name);
}
strcpy(szWin16Name, pszTearoffMethod);
}
// lower case the name.
_strlwr(szWin16Name);
// make sure the generated name is different from the original one.
if ( !strcmp( pszTearoffMethod, szWin16Name) )
{
char *p = strstr(szWin16Name, "::");
// Ok, the Method name is all lower case, so we upper case the
// name after the First char. We also need to skip past the Class Name
// if any. Upper casing the whole name gave some other problems.
if ( p != NULL )
_strupr(p+2);
else
_strupr(szWin16Name+1);
}
}
BOOL CPDLParser::GenerateTearoffTable ( Token *pClassToken, Token *pTearoff, LPCSTR pszInterface, BOOL fMostDerived )
{
fprintf ( fpHDLFile, "// Tear-off table for class %s\n",
pClassToken -> GetTagValue ( CLASS_NAME ) );
if (IsSpecialTearoff(pTearoff))
{
fprintf ( fpHDLFile, "BEGIN_TEAROFF_TABLE_PROPDESC(%s, %s)\n",
pClassToken -> GetTagValue ( CLASS_NAME ),
pszInterface );
}
else
{
fprintf ( fpHDLFile, "BEGIN_TEAROFF_TABLE(%s, %s)\n",
pClassToken -> GetTagValue ( CLASS_NAME ),
pszInterface );
}
// Walk the interface heirarchy, starting at this classes primary
// interface, generate a fn table for each interface encountered
// started with IDispatch methods above. Generate methods in interface order - deepest
// first
if ( !GenerateTearOffMethods ( pClassToken -> GetTagValue ( CLASS_NAME ), pTearoff, pszInterface, fMostDerived) )
return FALSE;
fprintf ( fpHDLFile, "END_TEAROFF_TABLE()\n\n" );
return TRUE;
}
Token *CPDLParser::GetSuperClassTokenPtr ( Token *pClassToken )
{
Token *pSuperToken = NULL;
if ( pClassToken -> IsSet ( CLASS_SUPER ) )
{
CTokenListWalker WholeList ( pRuntimeList );
pSuperToken = WholeList.GetNext ( TYPE_CLASS,
pClassToken -> GetTagValue ( CLASS_SUPER ) );
}
return pSuperToken;
}
BOOL CPDLParser::HasClassGotProperties ( Token *pClassToken )
{
Token *pSuperClass;
CTokenListWalker PropList ( pClassToken );
if ( PropList.GetNext ( TYPE_PROPERTY ) )
return TRUE;
else
{
pSuperClass = GetSuperClassTokenPtr ( pClassToken );
if ( pSuperClass )
return HasClassGotProperties ( pSuperClass );
else
return FALSE;
}
}
BOOL CPDLParser::PrimaryTearoff (Token *pInterface)
{
return !pInterface->IsSet(INTERFACE_NOPRIMARYTEAROFF);
}
Token * CPDLParser::NextTearoff (LPCSTR szClassname, Token *pLastTearoff /*= NULL*/)
{
CTokenListWalker ThisFilesList(pRuntimeList, _pszPDLFileName);
Token *pTearoffToken;
BOOL fNextOne = FALSE;
while (pTearoffToken = ThisFilesList.GetNext(TYPE_TEAROFF))
{
if (_stricmp(szClassname, (LPSTR)pTearoffToken->GetTagValue(TEAROFF_NAME)) == 0)
{
// The correct class.
if (pLastTearoff)
{
// Return this one.
if (!fNextOne)
{
fNextOne = pLastTearoff == pTearoffToken;
continue; // Get the next and then stop.
}
}
break;
}
}
return pTearoffToken;
}
Token* CPDLParser::FindTearoff (LPCSTR szClassname, LPCSTR szInterface)
{
Token *pLastTearoff = NULL;
while (pLastTearoff = NextTearoff(szClassname, pLastTearoff))
{
if (!_stricmp(szInterface, (LPSTR)pLastTearoff->GetTagValue(TEAROFF_INTERFACE)))
{
break;
}
}
return pLastTearoff;
}
BOOL CPDLParser::GenerateClassIncludes (void)
{
Token *pClassToken;
CTokenListWalker ThisFilesList(pRuntimeList, _pszPDLFileName);
// Walk the class statments for this file only
fprintf(fpLOGFile, "*** Looking for \"%s\"\n",_pszPDLFileName);
while (pClassToken = ThisFilesList.GetNext(TYPE_CLASS))
{
LPCSTR szClassname = (LPCSTR)pClassToken->GetTagValue(CLASS_NAME);
fprintf(fpHDLFile, "#ifdef _%s_\n\n", szClassname);
// Write out inline cached get helpers
fprintf(fpHDLFile,
"\n// Cascaded Property get method prototypes for class %s\n\npublic:\n",
szClassname);
GenerateGetAAXPrototypes(pClassToken);
fprintf(fpHDLFile,
"\n// Property get/set method declarations for class %s\n",
szClassname);
// Always add a propdesc declaration for non-abstract classes, remember
// abstract class haven't got a propertydesc array.
// TODO: TerryLu - Need to add code here to handle the shared keyword
if ((!pClassToken->IsSet(CLASS_ABSTRACT)) ||
(_stricmp(pClassToken->GetTagValue(CLASS_NAME), "CElement") == 0))
{
if(_stricmp(pClassToken->GetTagValue(CLASS_NAME), "CElement") != 0)
{
fprintf(fpHDLFile,
" static const HDLDESC %s::s_apHdlDescs;\n",
szClassname);
}
fprintf(fpHDLFile,
" static const CAssocVTable * const s_AssocVTablePtr[];\n");
fprintf(fpHDLFile,
" static const CAssocArrayVTable s_StringTable;\n");
fprintf(fpHDLFile,
" static const CPtrBagVTableAggregate s_StringTableAggregate;\n");
if(_stricmp(pClassToken->GetTagValue(CLASS_NAME), "COmWindowProxy") == 0)
{
fprintf(fpHDLFile, "static const VTABLEDESC * const COmWindowProxy::s_COmWindowProxyDocument;\n");
}
}
CString szInterface;
Token *pInterface;
BOOL fOk;
Token *pTearoff = NULL;
while ((pTearoff = NextTearoff(szClassname, pTearoff)))
{
szInterface = pTearoff->GetTagValue(TEAROFF_INTERFACE);
pInterface = FindInterface(szInterface);
if (pInterface)
{
CTokenListWalker ChildList(pInterface);
Token *pChildToken = ChildList.GetNext();
if (pChildToken)
{
fOk = FALSE;
do
{
if (pChildToken->GetType() == TYPE_PROPERTY && !pChildToken->IsSet(PROPERTY_ABSTRACT) && !pChildToken->IsSet(PROPERTY_BASEIMPLEMENTATION))
{
fOk = TRUE;
break;
}
} while (pChildToken = ChildList.GetNext());
if (fOk)
{
fprintf(fpHDLFile, " static const PROPERTYDESC * const %s::s_ppropdescsInVtblOrder%s [];\n",
szClassname, (LPSTR)pTearoff->GetTagValue(TEAROFF_INTERFACE));
}
}
}
}
// Generate a CPC if, we have an eventset && it is unique to us
if ( IsUniqueCPC ( pClassToken ) )
{
fprintf(fpHDLFile,
" static const CONNECTION_POINT_INFO %s::s_acpi[];\n",
szClassname);
}
GeneratePropMethodDecl(pClassToken);
if (pClassToken->IsSet(CLASS_EVENTS))
{
if (!GenerateEventFireDecl(pClassToken))
{
return FALSE;
}
}
// Whip thru all tearoffs.
Token *pLastTearoff = NULL;
while ((pLastTearoff = NextTearoff(szClassname, pLastTearoff)))
{
// Need static tearoff table decl
if (IsSpecialTearoff(pLastTearoff))
{
fprintf(fpHDLFile, " DECLARE_TEAROFF_TABLE_PROPDESC(%s)\n",
pLastTearoff->GetTagValue(TEAROFF_INTERFACE));
}
else
{
fprintf(fpHDLFile, " DECLARE_TEAROFF_TABLE(%s)\n",
pLastTearoff->GetTagValue(TEAROFF_INTERFACE));
}
}
GenerateThunkContext(pClassToken);
fprintf(fpHDLFile, "\n#endif // _%s_\n\n", szClassname);
fprintf(fpHDLFile, "#undef _%s_\n\n", szClassname);
}
return TRUE;
}
// Work out if this class has a unique connection point info structure -
// or can we use its super ??
BOOL CPDLParser::IsUniqueCPC ( Token *pClassToken )
{
BOOL fDoIt = FALSE;
Token *pClass;
CString szSuperClass, szThisEvents, szThatEvents;
if ( !pClassToken->IsSet(CLASS_NOCPC) && pClassToken->IsSet ( CLASS_EVENTS ) )
{
szThisEvents = pClassToken->GetTagValue(CLASS_EVENTS);
fDoIt = TRUE;
for ( pClass = pClassToken ; pClass ; )
{
if ( pClass->IsSet ( CLASS_SUPER ) )
{
szSuperClass = pClass -> GetTagValue ( CLASS_SUPER );
pClass = FindClass ( szSuperClass );
if ( pClass && pClass->IsSet ( CLASS_EVENTS ) && !pClass->IsSet(CLASS_NOCPC) )
{
szThatEvents = pClass->GetTagValue(CLASS_EVENTS);
if ( szThatEvents == szThisEvents )
{
// Do we have non-primary events #1 and is the super non-primary events
// the same as ours? If not, then we are unique.
if (pClassToken->IsSet(CLASS_NONPRIMARYEVENTS1))
{
szThisEvents = pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS1);
szThatEvents = pClass->GetTagValue(CLASS_NONPRIMARYEVENTS1);
if (szThatEvents != szThisEvents)
{
// We're unique.
break;
}
// Do we have non-primary events #2 and is the super non-primary events
// the same as ours? If not, then we are unique.
if (pClassToken->IsSet(CLASS_NONPRIMARYEVENTS2))
{
szThisEvents = pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS2);
szThatEvents = pClass->GetTagValue(CLASS_NONPRIMARYEVENTS2);
if (szThatEvents != szThisEvents)
{
// We're unique.
break;
}
// Do we have non-primary events #3 and is the super non-primary events
// the same as ours? If not, then we are unique.
if (pClassToken->IsSet(CLASS_NONPRIMARYEVENTS3))
{
szThisEvents = pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS3);
szThatEvents = pClass->GetTagValue(CLASS_NONPRIMARYEVENTS3);
if (szThatEvents != szThisEvents)
{
// We're unique.
break;
}
// Do we have non-primary events #4 and is the super non-primary events
// the same as ours? If not, then we are unique.
if (pClassToken->IsSet(CLASS_NONPRIMARYEVENTS4))
{
szThisEvents = pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS4);
szThatEvents = pClass->GetTagValue(CLASS_NONPRIMARYEVENTS4);
if (szThatEvents != szThisEvents)
{
// We're unique.
break;
}
}
}
}
// else fall through to below which set's fDoIt to FALSE.
}
fDoIt = FALSE;
break;
}
break;
}
}
else
break;
}
}
return fDoIt;
}
BOOL CPDLParser::GenerateEventFireDecl ( Token *pClassToken )
{
Token *pEventToken;
fprintf ( fpHDLFile, "// Event fire method declarations for events %s\n",
pClassToken -> GetTagValue ( CLASS_EVENTS ) );
// Find the event declaration
CTokenListWalker WholeList ( pRuntimeList ) ;
pEventToken = WholeList.GetNext ( TYPE_EVENT, pClassToken -> GetTagValue ( CLASS_EVENTS ) );
if ( pEventToken == NULL )
{
return FALSE;
}
return GenerateEventDecl ( pClassToken, pEventToken );
}
BOOL CPDLParser::IsElementEvent(Token *pEventInterface)
{
CTokenListWalker WholeList(pRuntimeList);
CString szEvent;
CString szElementEvent;
if (!pEventInterface)
return FALSE;
szEvent = pEventInterface->GetTagValue(EVENT_NAME);
if (_stricmp((LPCSTR)szEvent, "HTMLObjectElementEvents") == 0)
return TRUE;
szElementEvent = "HTMLElementEvents";
while (pEventInterface)
{
if (szElementEvent == szEvent)
return TRUE;
szEvent = pEventInterface->GetTagValue(EVENT_SUPER);
WholeList.Reset();
pEventInterface = WholeList.GetNext(TYPE_EVENT, szEvent);
}
return FALSE;
}
BOOL CPDLParser::GenerateEventDecl ( Token *pClassToken, Token *pEventToken )
{
/* TLL: Don't spit out any arguments. Currently the only argument for event is eventObject which is computed
Token *pArgToken;
*/
Token *pChildToken;
char szErrorText [ MAX_LINE_LEN+1 ];
CTokenListWalker ChildList ( pEventToken );
CString szNameUpper;
CString szNameLower;
BOOL fDocEvents = (_stricmp(pClassToken->GetTagValue(CLASS_EVENTS), "HTMLDocumentEvents") == 0) ||
(_stricmp(pClassToken->GetTagValue(CLASS_EVENTS), "HTMLProtectedElementEvents") == 0) ||
(_stricmp(pClassToken->GetTagValue(CLASS_EVENTS), "HTMLNamespaceEvents") == 0);
BOOL fWindowEvents = _stricmp(pClassToken->GetTagValue(CLASS_EVENTS), "HTMLWindowEvents") == 0;
BOOL fElementEvents = !fDocEvents && !fWindowEvents && IsElementEvent(pEventToken);
while ( pChildToken = ChildList.GetNext() )
{
if (!fElementEvents && !fDocEvents && !fWindowEvents &&
(_stricmp(pClassToken->GetTagValue(CLASS_EVENTS), "DWebBridgeEvents") != 0))
{
sprintf ( szErrorText, "Need to modify GenerateEventDecl() in parser.cpp to pass in Doc ptr to FireEvent for class:%s\n",
(LPCSTR)pClassToken->GetTagValue(CLASS_NAME) );
ReportError ( szErrorText );
return FALSE;
}
if ( pChildToken -> GetType() == TYPE_METHOD &&
!pChildToken -> IsSet ( METHOD_ABSTRACT ) )
{
szNameUpper = pChildToken -> GetTagValue ( METHOD_NAME );
szNameLower = szNameUpper;
szNameUpper.ToUpper();
if (!FindEventProp(pClassToken, (LPCSTR)szNameLower))
continue;
// Method
fprintf ( fpHDLFile, " %s Fire_%s(",
pChildToken->IsSet(METHOD_CANCELABLE) ? "BOOL" : "void",
pChildToken -> GetTagValue ( METHOD_NAME ) );
CTokenListWalker ArgListWalker ( pChildToken );
BOOL fFirst = TRUE;
/* TLL: Don't spit out any arguments. Currently the only argument for event is eventObject which is computed
while ( pArgToken = ArgListWalker.GetNext() )
{
if ( !fFirst )
fprintf ( fpHDLFile, "," );
fprintf ( fpHDLFile, "%s %s",
(LPCSTR)pArgToken -> GetTagValue ( METHODARG_TYPE ),
(LPCSTR)pArgToken -> GetTagValue ( METHODARG_ARGNAME ));
fFirst = FALSE;
}
*/
if ( pChildToken->IsSet(METHOD_BUBBLING) )
{
if ( !fFirst )
fprintf ( fpHDLFile, "," );
fprintf ( fpHDLFile, "CTreeNode * pNodeContext = NULL");
fprintf ( fpHDLFile, ", long lSubDivision = -1");
}
fprintf ( fpHDLFile, ")\n {\n " );
if ( pChildToken->IsSet(METHOD_CANCELABLE) )
{
fprintf ( fpHDLFile, "return !!" );
}
if (fElementEvents)
{
fprintf(fpHDLFile, "FireEvent(&s_propdesc%s%s%s",
(LPCSTR)pClassToken->GetTagValue(CLASS_NAME),
(LPCSTR)szNameLower,
pChildToken->IsSet(METHOD_BUBBLING) ? ", TRUE, pNodeContext, lSubDivision" : "");
}
else
{
fprintf(fpHDLFile, "FireEvent(%sDISPID_EVMETH_%s, DISPID_EVPROP_%s, _T(\"%s\")",
fDocEvents ? "Doc(), " : (fWindowEvents ? "_pDoc, " : ""),
(LPCSTR)szNameUpper,
(LPCSTR)szNameUpper,
(LPCSTR)szNameLower+2);
}
/* TLL: Don't spit out any arguments. Currently the only argument for event is eventObject which is computed
ArgListWalker.Reset();
if ( ArgListWalker.GetTokenCount() > 0 )
{
while ( pArgToken = ArgListWalker.GetNext() )
{
// Locate the vts type for this type
CString szVTSType;
if ( !LookupEventType ( szVTSType, pArgToken -> GetTagValue ( METHODARG_TYPE ) ) )
{
sprintf ( szErrorText, "Unknown Type %s in %s::Fire%s event declaration\n",
(LPCSTR) pArgToken -> GetTagValue ( METHODARG_TYPE ),
pEventToken -> GetTagValue ( EVENT_NAME ),
pChildToken -> GetTagValue ( METHOD_NAME ) );
ReportError ( szErrorText );
return FALSE;
}
fprintf ( fpHDLFile, " %s", (LPCSTR)szVTSType );
fFirst = FALSE;
}
ArgListWalker.Reset();
while ( pArgToken = ArgListWalker.GetNext() )
{
fprintf ( fpHDLFile, ", %s",
pArgToken -> GetTagValue ( METHODARG_ARGNAME ) );
}
}
else
{
fprintf ( fpHDLFile, " VTS_NONE" );
}
*/
fprintf ( fpHDLFile, ");\n }\n" );
}
else if ( pChildToken -> GetType() == TYPE_PROPERTY )
{
// Property in event set - should never happen if we
// check the child/parent relationships at parse time
sprintf ( szErrorText, "events %s - invalid to have a property in event set\n",
(LPCSTR)pClassToken -> GetTagValue ( EVENT_NAME ) );
ReportError ( szErrorText );
return FALSE;
}
}
return TRUE;
}
LPCSTR CPDLParser::ConvertType(LPCSTR szType, BOOL fComPlus /* = FALSE*/, LPSTR pCPString /* = 0*/, BOOL *pfInterfaceFound /* = 0*/)
{
if (!fComPlus)
{
if (_stricmp(szType, "SAFEARRAY(VARIANT)") == 0)
return("SAFEARRAY*");
else
return(szType);
}
else
{
BOOL fInterfFound;
if (!pfInterfaceFound)
{
pfInterfaceFound = &fInterfFound;
}
*pfInterfaceFound = FALSE;
if (_stricmp(szType, "BSTR") == 0)
return("String");
else if (_stricmp(szType, "VARIANT_BOOL") == 0)
return("Boolean");
else if (_stricmp(szType, "VARIANT") == 0)
return("Variant");
else if (_stricmp(szType, "IDispatch") == 0 || _stricmp(szType, "IUnknown") == 0)
return("Object");
else if (_stricmp(szType, "SAFEARRAY(VARIANT)") == 0)
return("String"); // ***TLL*** COM+: Need to make it a safearray
else if (pCPString)
{
CString pInterf;
pInterf = szType;
if (FindInterface(pInterf))
{
strcpy(pCPString, szType);
strcat(pCPString, "COMPLUS");
*pfInterfaceFound = TRUE;
return 0;
}
else
{
return(szType);
}
}
else
return(szType);
}
}
void CPDLParser::GeneratePropMethodDecl ( Token *pClassToken )
{
CTokenListWalker ChildList ( pClassToken );
CString szProp;
Token *pArgToken;
Token *pChildToken;
char szContextThunk[] = "ContextThunk_";
LPCSTR pCtxt;
while ( pChildToken = ChildList.GetNext() )
{
char szTemp[256];
LPSTR pMethodName;
BOOL fNameOnly;
fNameOnly = _stricmp(pChildToken->GetTagValue(METHOD_NOPROPDESC), "nameonly") == 0;
if ( pChildToken -> GetType() == TYPE_METHOD && !fNameOnly )
{
// Method
fprintf ( fpHDLFile, " " );
if ( pChildToken -> IsSet ( METHOD_VIRTUAL ) )
{
//fprintf ( fpHDLFile, "virtual " );
fprintf ( fpHDLFile, "DECLARE_TEAROFF_METHOD_(" );
}
else
fprintf ( fpHDLFile, "NV_DECLARE_TEAROFF_METHOD_(" );
pMethodName = pChildToken->IsSet(METHOD_SZINTERFACEEXPOSE) ?
(LPSTR)pChildToken->GetTagValue(METHOD_SZINTERFACEEXPOSE) :
(LPSTR)pChildToken->GetTagValue(METHOD_NAME);
GenerateWin16TearoffName(szTemp, pMethodName);
pCtxt = pChildToken->IsSet(METHOD_THUNKCONTEXT) ||
pChildToken->IsSet(METHOD_THUNKNODECONTEXT)
? szContextThunk : "";
//fprintf ( fpHDLFile, "%s STDMETHODCALLTYPE %s(",
fprintf ( fpHDLFile, "%s, %s%s, %s, (",
pChildToken -> GetTagValue ( METHOD_RETURNTYPE ),
pCtxt, pMethodName, szTemp );
CTokenListWalker ArgListWalker ( pChildToken );
BOOL fFirst = TRUE;
while ( pArgToken = ArgListWalker.GetNext() )
{
if ( !fFirst )
fprintf ( fpHDLFile, "," );
fprintf ( fpHDLFile, "%s %s",
ConvertType((LPCSTR)pArgToken -> GetTagValue ( METHODARG_TYPE )),
(LPCSTR)pArgToken -> GetTagValue ( METHODARG_ARGNAME ) );
fFirst = FALSE;
}
fprintf ( fpHDLFile, "));\n" );
}
else
{
fNameOnly = _stricmp(pChildToken->GetTagValue(PROPERTY_NOPROPDESC), "nameonly") == 0;
// Base has provided prototoype
if ( pChildToken -> IsSet ( PROPERTY_BASEIMPLEMENTATION )
|| (!pChildToken->IsSet(PROPERTY_ABSTRACT) && IsSpecialProperty(pClassToken))
)
{
continue;
}
// Property
szProp = "";
// Through the index/indextype & index1/indextype1 pdl tags
// you can provide up to two additional args for the property definition
if ( pChildToken -> IsSet ( PROPERTY_INDEX ) )
{
szProp += pChildToken -> GetTagValue ( PROPERTY_INDEXTYPE );
szProp += " ";
szProp += pChildToken -> GetTagValue ( PROPERTY_INDEX );
}
if ( pChildToken -> IsSet ( PROPERTY_INDEX1 ) )
{
if ( szProp [ 0 ] != '\0' )
szProp += ",";
szProp += pChildToken -> GetTagValue ( PROPERTY_INDEXTYPE1 );
szProp += " ";
szProp += pChildToken -> GetTagValue ( PROPERTY_INDEX1 );
}
if ( szProp [ 0 ] != '\0' )
szProp += ",";
pMethodName = pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
(LPSTR)pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
(LPSTR)pChildToken->GetTagValue(PROPERTY_NAME);
pCtxt = pChildToken->IsSet(PROPERTY_THUNKCONTEXT) ||
pChildToken->IsSet(PROPERTY_THUNKNODECONTEXT)
? szContextThunk : "";
if ( pChildToken -> IsSet ( PROPERTY_SET ) && !fNameOnly )
{
fprintf ( fpHDLFile, " " );
if ( pChildToken -> IsSet ( PROPERTY_VIRTUAL ) )
{
fprintf ( fpHDLFile, "DECLARE_TEAROFF_METHOD(%sput_%s, PUT_%s, (%s%s v));\n",
pCtxt,
pMethodName,
pMethodName,
(LPCSTR)szProp,
(LPCSTR)pChildToken -> GetTagValue ( PROPERTY_ATYPE ));
}
else
{
fprintf ( fpHDLFile, "NV_DECLARE_TEAROFF_METHOD(%sput_%s, PUT_%s, (%s%s v));\n",
pCtxt,
pMethodName,
pMethodName,
(LPCSTR)szProp,
(LPCSTR)pChildToken -> GetTagValue ( PROPERTY_ATYPE ));
}
}
if ( pChildToken -> IsSet ( PROPERTY_GET ) && !fNameOnly)
{
fprintf ( fpHDLFile, " " );
if ( pChildToken -> IsSet ( PROPERTY_VIRTUAL ) )
{
fprintf ( fpHDLFile, "DECLARE_TEAROFF_METHOD(%sget_%s, GET_%s, (%s%s*p));\n",
pCtxt,
pMethodName,
pMethodName,
(LPCSTR)szProp,
(LPCSTR)pChildToken -> GetTagValue ( PROPERTY_ATYPE ));
}
else
{
fprintf ( fpHDLFile, "NV_DECLARE_TEAROFF_METHOD(%sget_%s, GET_%s, (%s%s*p));\n",
pCtxt,
pMethodName,
pMethodName,
(LPCSTR)szProp,
(LPCSTR)pChildToken -> GetTagValue ( PROPERTY_ATYPE ));
}
}
}
}
}
BOOL CPDLParser::IsStoredAsString( Token *pChildToken )
{
CString szJunk1, szJunk2;
StorageType stHowStored;
GetTypeDetails ( pChildToken->GetTagValue ( PROPERTY_TYPE ),
szJunk1, szJunk2, &stHowStored );
return stHowStored == STORAGETYPE_STRING ? TRUE : FALSE;
}
void CPDLParser::GenerateGetAAXPrototypes ( Token *pClassToken )
{
CTokenListWalker ChildList ( pClassToken );
Token *pChildToken;
if ( pClassToken -> IsSet ( CLASS_NOAAMETHODS ) )
return;
while ( pChildToken = ChildList.GetNext() )
{
// Generate a GetAA prototype even if the automation Get method is not generated
if ( pChildToken -> GetType() != TYPE_METHOD &&
pChildToken -> IsSet ( PROPERTY_CAA ) &&
_stricmp(pChildToken->GetTagValue(PROPERTY_NOPROPDESC), "nameonly"))
{
BOOL fIsString = IsStoredAsString(pChildToken);
//setaahr method
if (pChildToken -> IsSet ( PROPERTY_SETAAHR ) )
{
fprintf ( fpHDLFile, " HRESULT SetAA%s(%s);\n",
(LPCSTR)pChildToken -> GetTagValue ( PROPERTY_NAME ),
(LPCSTR)(fIsString?"LPCTSTR": (LPCSTR)pChildToken -> GetTagValue ( PROPERTY_TYPE ) )
);
}
//get method. If the property refers to a cascaded format - don't generate a GetAA - this would just
// encourage mis-use. Always want to force use of GetCascadedXX variant
if ( !pChildToken -> IsSet ( PROPERTY_CASCADED ) ||
pChildToken -> IsSet ( PROPERTY_GETAA ) )
{
fprintf ( fpHDLFile, " %s GetAA%s() const;\n",
(LPCSTR)(fIsString?"LPCTSTR":(LPCSTR)pChildToken -> GetTagValue ( PROPERTY_TYPE )),
(LPCSTR)(pChildToken->GetTagValue ( PROPERTY_NAME )) );
}
}
}
}
void CPDLParser::GenerateGetAAXImplementations( Token *pClassToken )
{
CTokenListWalker ChildList ( pClassToken );
Token *pChildToken;
if ( pClassToken -> IsSet ( CLASS_NOAAMETHODS ) )
return;
while ( pChildToken = ChildList.GetNext() )
{
// Generate a GetAA prototype even if the automation Get method is not generated
if ( pChildToken -> GetType() != TYPE_METHOD &&
pChildToken -> IsSet ( PROPERTY_CAA ) &&
_stricmp(pChildToken->GetTagValue(PROPERTY_NOPROPDESC), "nameonly"))
{
BOOL fIsString = IsStoredAsString(pChildToken);
//setaahr method
if (pChildToken -> IsSet ( PROPERTY_SETAAHR ) )
{
if (!strcmp((LPCSTR)pChildToken ->GetTagValue(PROPERTY_TYPE), "VARIANT_BOOL"))
{
fprintf ( fpHDLFile, "HRESULT %s::SetAA%s(VARIANT_BOOL pv)\n{\n DWORD dwTemp = pv;\n RRETURN( THR( CAttrArray::SetSimple(GetAttrArray(), &s_propdesc%s%s.a, dwTemp) ) );\n}\n",
(LPCSTR)pClassToken -> GetTagValue ( CLASS_NAME ),
(LPCSTR)pChildToken -> GetTagValue ( PROPERTY_NAME ),
(LPCSTR)pClassToken -> GetTagValue ( CLASS_NAME ),
(LPCSTR)pChildToken -> GetTagValue ( PROPERTY_NAME )
);
}
else
{
fprintf ( fpHDLFile, "HRESULT %s::SetAA%s(%s pv)\n{\n RRETURN( THR( CAttrArray::Set%s(GetAttrArray(), &s_propdesc%s%s.a, %spv) ) );\n}\n",
(LPCSTR)pClassToken -> GetTagValue ( CLASS_NAME ),
(LPCSTR)pChildToken -> GetTagValue ( PROPERTY_NAME ),
(LPCSTR)( fIsString?"LPCTSTR":(LPCSTR)pChildToken ->GetTagValue(PROPERTY_TYPE) ),
(LPCSTR)(fIsString?"String":"Simple"),
(LPCSTR)pClassToken -> GetTagValue ( CLASS_NAME ),
(LPCSTR)pChildToken -> GetTagValue ( PROPERTY_NAME ),
(LPCSTR)(fIsString?"":"*(DWORD*) &")
);
}
}
//get method. Don't generate a GetAA - they already have a GetCascadedX
if ( !pChildToken -> IsSet ( PROPERTY_CASCADED ) ||
pChildToken -> IsSet ( PROPERTY_GETAA ) )
{
Token *pExposeToken = NULL;
CString szClass;
if (pChildToken -> IsSet ( PROPERTY_NOPROPDESC ))
{
pExposeToken = FindMatchingEntryWOPropDesc(pClassToken, pChildToken);
}
if (!pExposeToken)
pExposeToken = pChildToken;
if (strlen( pExposeToken -> GetTagValue ( PROPERTY_REFDTOCLASS )))
szClass = pExposeToken -> GetTagValue ( PROPERTY_REFDTOCLASS );
else
szClass = (LPCSTR)pClassToken -> GetTagValue ( CLASS_NAME );
#ifdef UNIX // IEUNIX: On Unix, converting DWORD* to short* would cause value changed. So we cast it from DWORD to short.
if (!fIsString)
{
LPCSTR pPropType = (LPCSTR)pChildToken->GetTagValue( PROPERTY_TYPE);
if ( !_stricmp(pPropType , "short") || !_stricmp(pPropType, "WORD") || !_stricmp(pPropType, "BYTE") )
{
fprintf ( fpHDLFile, "%s %s::GetAA%s() const \n{\n DWORD v;\n CAttrArray::FindSimple( *GetAttrArray(), &s_propdesc%s%s.a, &v);\n return (%s)v;\n}\n",
pPropType,
(LPCSTR)pClassToken -> GetTagValue ( CLASS_NAME ),
(LPCSTR)(pChildToken->GetTagValue ( PROPERTY_NAME )),
(LPCSTR)szClass,
(LPCSTR)pChildToken -> GetTagValue ( PROPERTY_NAME ),
pPropType );
continue;
}
}
#endif
fprintf ( fpHDLFile, "%s %s::GetAA%s() const \n{\n %s v;\n CAttrArray::Find%s( *GetAttrArray(), &s_propdesc%s%s.a, &v);\n return *(%s*)&v;\n}\n",
(LPCSTR)(fIsString?"LPCTSTR":(LPCSTR)pChildToken -> GetTagValue ( PROPERTY_TYPE )),
(LPCSTR)pClassToken -> GetTagValue ( CLASS_NAME ),
(LPCSTR)(pChildToken->GetTagValue ( PROPERTY_NAME )) ,
(LPCSTR)(fIsString?"LPCTSTR":"DWORD" ),
(LPCSTR)(fIsString?"String":"Simple"),
(LPCSTR)szClass,
(LPCSTR)pChildToken -> GetTagValue ( PROPERTY_NAME ),
(LPCSTR)(fIsString?"LPCTSTR":(LPCSTR)pChildToken -> GetTagValue ( PROPERTY_TYPE ) ) );
}
}
}
}
BOOL CPDLParser::GenerateIDispatchTearoff ( LPCSTR szClassName, Token *pTearoff, LPCSTR pszInterface, BOOL fMostDerived)
{
char szTearoffMethod[128];
char szTemp[128];
fprintf ( fpHDLFile, " // IDispatch methods\n");
FindTearoffMethod(pTearoff, "GetTypeInfoCount", szTearoffMethod);
GenerateWin16TearoffName(szTemp, szTearoffMethod);
fprintf ( fpHDLFile, " TEAROFF_METHOD(%s, %s, %s, (unsigned int *))\n",
szClassName, szTearoffMethod, szTemp);
FindTearoffMethod(pTearoff, "GetTypeInfo", szTearoffMethod);
GenerateWin16TearoffName(szTemp, szTearoffMethod);
fprintf ( fpHDLFile, " TEAROFF_METHOD(%s, %s, %s, (unsigned int, unsigned long, ITypeInfo **))\n",
szClassName, szTearoffMethod, szTemp);
FindTearoffMethod(pTearoff, "GetIDsOfNames", szTearoffMethod);
GenerateWin16TearoffName(szTemp, szTearoffMethod);
fprintf ( fpHDLFile, " TEAROFF_METHOD(%s, %s, %s, (REFIID, LPOLESTR *, unsigned int, LCID, DISPID *))\n",
szClassName, szTearoffMethod, szTemp);
{
CString szIHTMLElement, szInterface;
szIHTMLElement = "IHTMLElement";
szInterface = pszInterface;
if(!FindTearoffMethod(pTearoff, "Invoke", szTearoffMethod) &&
IsSuperInterface(szIHTMLElement, FindInterface(szInterface)))
{
strcpy(szTearoffMethod, pTearoff->IsSet(TEAROFF_BASEIMPL) ?
(LPCSTR)pTearoff->GetTagValue(TEAROFF_BASEIMPL) : "");
strcat(szTearoffMethod, "ContextThunk_Invoke");
}
}
GenerateWin16TearoffName(szTemp, szTearoffMethod);
fprintf ( fpHDLFile, " TEAROFF_METHOD(%s, %s, %s, (DISPID, REFIID, LCID, WORD, DISPPARAMS *, VARIANT *, EXCEPINFO *, unsigned int *))\n",
szClassName, szTearoffMethod, szTemp);
return TRUE;
}
BOOL CPDLParser::IsSpecialTearoff(Token *pTearoff)
{
CString szInterface;
Token *pInterface;
Token *pChildToken;
szInterface = pTearoff->GetTagValue(TEAROFF_INTERFACE);
pInterface = FindInterface(szInterface);
if (!pInterface || pInterface->IsSet(INTERFACE_ABSTRACT))
return FALSE;
CTokenListWalker ChildList(pInterface);
pChildToken = ChildList.GetNext();
if (pChildToken)
{
do
{
if (pChildToken->GetType() == TYPE_PROPERTY && !pChildToken->IsSet(PROPERTY_ABSTRACT) && !pChildToken->IsSet(PROPERTY_BASEIMPLEMENTATION))
{
return TRUE;
}
} while (pChildToken = ChildList.GetNext());
}
return FALSE;
}
BOOL CPDLParser::FindTearoffProperty(Token *pPropertyToken, LPSTR szTearoffMethod,
LPSTR szTearOffClassName, LPSTR szPropArgs, BOOL fPropGet)
{
if (pPropertyToken->IsSet(PROPERTY_ABSTRACT) || pPropertyToken->IsSet(PROPERTY_BASEIMPLEMENTATION))
return FALSE;
strcpy(szTearoffMethod, fPropGet ? "get_" : "put_");
strcpy(szPropArgs, fPropGet ? "void" : (LPCSTR)pPropertyToken->GetTagValue(PROPERTY_ATYPE));
strcpy(szTearOffClassName, "CBase");
if (!strcmp(pPropertyToken->GetTagValue(PROPERTY_ATYPE), "VARIANT"))
{
if (fPropGet)
{
strcat(szTearoffMethod, "Property");
}
else if (pPropertyToken->IsSet(PROPERTY_DATAEVENT))
strcat(szTearoffMethod, "DataEvent");
else
strcat(szTearoffMethod, "Variant");
}
else if (!strcmp(pPropertyToken->GetTagValue(PROPERTY_ATYPE), "BSTR"))
{
if (!strcmp(pPropertyToken->GetTagValue(PROPERTY_TYPE), "url"))
{
strcat(szTearoffMethod, "Url");
strcpy(szPropArgs, (LPCSTR)pPropertyToken->GetTagValue(PROPERTY_ATYPE));
}
else if (!strcmp(pPropertyToken->GetTagValue(PROPERTY_TYPE), "CStyleComponent"))
{
strcat(szTearoffMethod, "StyleComponent");
strcpy(szPropArgs, (LPCSTR)pPropertyToken->GetTagValue(PROPERTY_ATYPE));
}
else
strcat(szTearoffMethod, (fPropGet ? "Property" : "String"));
}
else if (!strcmp(pPropertyToken->GetTagValue(PROPERTY_ATYPE), "VARIANT_BOOL"))
strcat(szTearoffMethod, (fPropGet ? "Property" : "Bool"));
else if (!strcmp(pPropertyToken->GetTagValue(PROPERTY_ATYPE), "long"))
strcat(szTearoffMethod, fPropGet ? "Property" : "Long");
else if (!strcmp(pPropertyToken->GetTagValue(PROPERTY_ATYPE), "short"))
strcat(szTearoffMethod, fPropGet ? "Property" : "Short");
else
{
char szError[124];
sprintf(szError, "%s: This property of new type needs a function prototype (in cdbase.hxx) and a body defn. in (baseprop.cxx)",
(LPCSTR)pPropertyToken->GetTagValue(PROPERTY_NAME));
ReportError (szError);
return FALSE;
}
return TRUE;
}
BOOL CPDLParser::GeneratePropDescsInVtblOrder(Token *pClassToken, int *pNumVtblPropDescs)
{
CString szPrimaryInterf;
CString szInterface;
LPCSTR szClassName = pClassToken->GetTagValue(CLASS_NAME);
BOOL fOk;
BOOL fNameOnly;
int i = 0, j;
szPrimaryInterf = pClassToken->GetTagValue(CLASS_INTERFACE);
Token *pPrimaryInterf = FindInterface(szPrimaryInterf);
Token *pInterface;
Token *pChildToken;
Token *apInterface[5];
*pNumVtblPropDescs = 0;
Token *pTearoff = NULL;
while ((pTearoff = NextTearoff(szClassName, pTearoff)))
{
szInterface = pTearoff->GetTagValue(TEAROFF_INTERFACE);
pInterface = FindInterface(szInterface);
if (!pInterface || pInterface->IsSet(INTERFACE_ABSTRACT))
continue;
i = 0;
apInterface[i++] = pInterface;
while (i < 5 && apInterface[i-1]->IsSet(INTERFACE_SUPER) &&
_stricmp(apInterface[i-1]->GetTagValue(INTERFACE_SUPER), "IDispatch") &&
_stricmp(apInterface[i-1]->GetTagValue(INTERFACE_SUPER), "IUnknown"))
{
szInterface = apInterface[i-1]->GetTagValue(INTERFACE_SUPER);
apInterface[i++] = FindInterface(szInterface);
}
if (i >= 5)
{
ReportError("Super Chain More than 5, Need to increase limit in PdlParser");
return FALSE;
}
fOk = FALSE;
CTokenListWalker ChildList(pInterface);
pChildToken = ChildList.GetNext();
if (pChildToken)
{
do
{
if (pChildToken->GetType() == TYPE_PROPERTY && !pChildToken->IsSet(PROPERTY_ABSTRACT) && !pChildToken->IsSet(PROPERTY_BASEIMPLEMENTATION))
{
fOk = TRUE;
break;
}
} while (pChildToken = ChildList.GetNext());
if (fOk)
{
fprintf(fpHDLFile, "\nconst PROPERTYDESC * const %s::s_ppropdescsInVtblOrder%s[] = {\n", szClassName,
(LPSTR)pTearoff->GetTagValue(TEAROFF_INTERFACE));
for (j = i-1; j >= 0; j--)
{
pInterface = apInterface[j];
CTokenListWalker ChildLst(pInterface);
pChildToken = ChildLst.GetNext();
do
{
char szErrorText[MAX_LINE_LEN + 1];
Token *pExposeToken = NULL;
if (pChildToken->GetType() == TYPE_METHOD)
{
if (pChildToken->IsSet(METHOD_NOPROPDESC))
{
fNameOnly = _stricmp(pChildToken->GetTagValue(METHOD_NOPROPDESC), "nameonly") == 0;
pExposeToken = FindMatchingEntryWOPropDesc(pClassToken, pChildToken, fNameOnly);
if (!pExposeToken)
{
sprintf(szErrorText,
"Function member marked as nopropdesc can not find exact signature match in new interface:%s in Class:%s\n",
(LPCSTR)pChildToken->GetTagValue(METHOD_NAME),
szClassName);
ReportError(szErrorText);
return FALSE;
}
}
else
pExposeToken = pChildToken;
fprintf(fpHDLFile, " (PROPERTYDESC *)&s_methdesc%s%s,\n", pExposeToken->GetTagValue((int)METHOD_REFDTOCLASS), pExposeToken->GetTagValue(METHOD_NAME));
if (pPrimaryInterf == pInterface)
(*pNumVtblPropDescs)++;
}
else
{
if (pChildToken->IsSet(PROPERTY_SET) || pChildToken->IsSet(PROPERTY_GET))
{
BOOL fDoAgain = TRUE;
DoAgain:
if (pChildToken->IsSet(PROPERTY_NOPROPDESC))
{
fNameOnly = _stricmp(pChildToken->GetTagValue(PROPERTY_NOPROPDESC), "nameonly") == 0;
pExposeToken = FindMatchingEntryWOPropDesc(pClassToken, pChildToken, fNameOnly);
if (!pExposeToken)
{
sprintf(szErrorText,
"Function member marked as nopropdesc can not find exact signature match in new interface:%s in Class:%s\n",
(LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME),
szClassName);
ReportError(szErrorText);
return FALSE;
}
}
else
pExposeToken = pChildToken;
pExposeToken = pExposeToken ? pExposeToken : pChildToken;
fprintf(fpHDLFile, " (const PROPERTYDESC *)&s_propdesc%s%s,\n",
pExposeToken->GetTagValue((int)PROPERTY_REFDTOCLASS),
pExposeToken->GetTagValue(PROPERTY_NAME));
if (pPrimaryInterf == pInterface)
(*pNumVtblPropDescs)++;
// If property is getter and setter both then generate another propdesc (but just once).
if (fDoAgain && pChildToken->IsSet(PROPERTY_SET) && pChildToken->IsSet(PROPERTY_GET))
{
fDoAgain = FALSE;
goto DoAgain;
}
}
}
} while (pChildToken = ChildLst.GetNext());
}
fprintf(fpHDLFile, "};\n\n");
}
}
}
return TRUE;
}
BOOL CPDLParser::GenerateTearOffMethods (LPCSTR szClassName, Token *pTearoff, LPCSTR szInterfaceName, BOOL fMostDerived)
{
Token *pInterfaceToken;
Token *pChildToken;
char szText[MAX_LINE_LEN+1];
CTokenListWalker WholeList(pRuntimeList);
#if 0
if (strcmp(_pszPDLFileName, "div.pdl") == 0 || strcmp(szInterfaceName, "IHTMLDivElement") == 0)
__asm { int 3 };
#endif
// Find the interface decl
do
{
pInterfaceToken = WholeList.GetNext(TYPE_INTERFACE, szInterfaceName);
if (pInterfaceToken == NULL)
{
// if the deepest is IDispatch output that tearoff
if (_stricmp(szInterfaceName, "IDispatch"))
{
// but IUnknowns are OK so return true
if (_stricmp(szInterfaceName, "IUnknown"))
{
// its something we don't recognise so output error msg
sprintf(szText, "interface:%s unknown\n", (LPCSTR)szInterfaceName);
ReportError(szText);
return FALSE;
}
else
return TRUE;
}
else
{
return GenerateIDispatchTearoff(szClassName, pTearoff, szInterfaceName, fMostDerived);
}
}
} while (!pInterfaceToken->IsSet(INTERFACE_GUID));
// If we only want most derived then we're done otherwise continue recursing.
if (!fMostDerived)
{
// Generate the interfaces super tear off methods first
if (pInterfaceToken->IsSet(INTERFACE_SUPER))
{
GenerateTearOffMethods(szClassName, pTearoff, pInterfaceToken->GetTagValue(INTERFACE_SUPER));
}
}
else
{
// fMostDerived is only set for the primary interface, which we don't want stacked ontop of its
// derivations. so all we want to do is dump in the dispatch and go on.
GenerateIDispatchTearoff(szClassName, pTearoff, szInterfaceName, fMostDerived);
}
// generate the fn prototypes cast to generic fn pts in the
// tearoff table
CTokenListWalker ChildList(pInterfaceToken);
CString szProp;
Token *pArgToken;
fprintf ( fpHDLFile, " // %s methods\n", szInterfaceName);
while (pChildToken = ChildList.GetNext())
{
char szTemp[256];
char szTearOffClassName[256];
char szContextThunk[] = "ContextThunk_";
LPCSTR pCtxt;
if (pChildToken->GetType() == TYPE_METHOD)
{
CTokenListWalker ArgListWalker(pChildToken);
BOOL fFirstArg = TRUE;
char szTearoffMethod[128];
LPCSTR pMethodName;
pMethodName = pChildToken->IsSet(METHOD_SZINTERFACEEXPOSE) ?
(LPSTR)pChildToken->GetTagValue(METHOD_SZINTERFACEEXPOSE) :
(LPSTR)pChildToken->GetTagValue(METHOD_NAME);
FindTearoffMethod(pTearoff,
pMethodName,
szTearoffMethod);
strcpy(szTearOffClassName, szClassName);
GenerateWin16TearoffName(szTemp, szTearoffMethod, szTearOffClassName);
pCtxt = pChildToken->IsSet(METHOD_THUNKCONTEXT) ||
pChildToken->IsSet(METHOD_THUNKNODECONTEXT)
? szContextThunk : "";
// Method
fprintf(fpHDLFile, " TEAROFF_METHOD(%s, %s%s, %s, (", szTearOffClassName, pCtxt, szTearoffMethod, szTemp);
// All automated methods MUST have an HRESULT for the return type.
if (_stricmp("HRESULT", (LPCSTR)pChildToken->GetTagValue(METHOD_RETURNTYPE)))
{
ReportError("Automated method must have HRESULT for return value\n");
return FALSE;
}
// Output each argument.
while (pArgToken = ArgListWalker.GetNext())
{
if (!fFirstArg)
fprintf(fpHDLFile, ",");
fprintf(fpHDLFile, "%s", ConvertType((LPCSTR)pArgToken->GetTagValue(METHODARG_TYPE)));
fFirstArg = FALSE;
}
fprintf(fpHDLFile, "))\n");
}
else
{
char szPropName[128];
char szTearoffMethod[128];
char szPropArgs[64];
LPCSTR pMethodName;
// Property
szProp = "";
pMethodName = pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
(LPSTR)pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
(LPSTR)pChildToken->GetTagValue(PROPERTY_NAME);
// Through the index/indextype & index1/indextype1 pdl tags
// you can provide up to two additional args for the property definition
pChildToken->AddParam(szProp, PROPERTY_INDEX, pChildToken->GetTagValue(PROPERTY_INDEXTYPE));
pChildToken->AddParam(szProp, PROPERTY_INDEX1, pChildToken->GetTagValue(PROPERTY_INDEXTYPE1));
if (szProp[0] != '\0')
szProp += ",";
pCtxt = pChildToken->IsSet(PROPERTY_THUNKCONTEXT) ||
pChildToken->IsSet(PROPERTY_THUNKNODECONTEXT)
? szContextThunk : "";
if ( pChildToken->IsSet(PROPERTY_SET))
{
strcpy(szPropName, "put_");
strcat(szPropName, pMethodName);
if (FindTearoffMethod(pTearoff, szPropName, szTearoffMethod))
{
strcpy(szPropArgs, (LPCSTR)pChildToken->GetTagValue(PROPERTY_ATYPE));
strcpy(szTearOffClassName, szClassName);
}
else if (!FindTearoffProperty(pChildToken, szTearoffMethod, szTearOffClassName, szPropArgs, FALSE))
{
FindTearoffMethod(pTearoff, szPropName, szTearoffMethod);
strcpy(szPropArgs, (LPCSTR)pChildToken->GetTagValue(PROPERTY_ATYPE));
strcpy(szTearOffClassName, szClassName);
}
GenerateWin16TearoffName(szTemp, szTearoffMethod, szTearOffClassName);
fprintf(fpHDLFile, " TEAROFF_METHOD(%s, %s%s, %s, (%s%s)) // property set_%s\n",
szTearOffClassName,
pCtxt,
szTearoffMethod,
szTemp,
(LPCSTR)szProp,
(LPCSTR)szPropArgs,
(LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME));
}
if (pChildToken->IsSet(PROPERTY_GET))
{
strcpy(szPropName, "get_");
strcat(szPropName, pMethodName);
if (FindTearoffMethod(pTearoff, szPropName, szTearoffMethod))
{
strcpy(szPropArgs, (LPCSTR)pChildToken->GetTagValue(PROPERTY_ATYPE));
strcpy(szTearOffClassName, szClassName);
}
else if (!FindTearoffProperty(pChildToken, szTearoffMethod, szTearOffClassName, szPropArgs, TRUE))
{
FindTearoffMethod(pTearoff, szPropName, szTearoffMethod);
strcpy(szPropArgs, (LPCSTR)pChildToken->GetTagValue(PROPERTY_ATYPE));
strcpy(szTearOffClassName, szClassName);
}
GenerateWin16TearoffName(szTemp, szTearoffMethod, szTearOffClassName);
fprintf(fpHDLFile, " TEAROFF_METHOD(%s, %s%s, %s, (%s%s *)) // property get_%s\n",
szTearOffClassName,
pCtxt,
szTearoffMethod,
szTemp,
(LPCSTR)szProp,
(LPCSTR)szPropArgs,
(LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME));
}
}
}
return TRUE;
}
void CPDLParser::GenerateMethodImp ( Token *pClassToken,
Token *pChildToken, BOOL fIsSet, CString &szHandler,
CString &szHandlerArgs, CString &szOffsetOf, CString &szAType )
{
#if COLLECT_STATISTICS==1
// Collect statistics on total property code turds.
CollectStatistic(NUM_PROPTURDS, GetStatistic(NUM_PROPTURDS) + 1);
#endif
char *szHandlerMethodPrefix;
char *szAutomationMethodPrefix;
if ( fIsSet )
{
szHandlerMethodPrefix = "Set";
szAutomationMethodPrefix = "put_";
}
else
{
szHandlerMethodPrefix = "Get";
szAutomationMethodPrefix = "get_";
}
// Allow enums with an ATYPE of BSTR to be automated with the string handler
if ( szHandler == "Enum" && szAType == "BSTR" )
{
szHandler = "EnumString";
#if COLLECT_STATISTICS==1
// Collect statistics on number of enum code turds.
CollectStatistic(NUM_EMUMTURDS, GetStatistic(NUM_EMUMTURDS) + 1);
#endif
}
fprintf ( fpHDLFile,
"STDMETHODIMP %s::%s%s(%s%s)\n{\n",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)szAutomationMethodPrefix,
(LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ),
(LPCSTR)szAType,
fIsSet ? " v" : " * p" );
if ( pChildToken -> IsSet ( PROPERTY_PRECALLFUNCTION ) )
{
CString szfn;
szfn = pChildToken -> GetTagValue ( PROPERTY_PRECALLFUNCTION ) ;
// Give the super a chance to reject the call
fprintf ( fpHDLFile, " HRESULT hr;\n" );
if ( szfn == "super" )
{
fprintf ( fpHDLFile, " hr = super::%s%s(%s);\n",
szAutomationMethodPrefix,
(LPCSTR)pChildToken->GetTagValue ( PROPERTY_PRECALLFUNCTION ),
fIsSet ? "v" : "p" );
}
else
{
fprintf ( fpHDLFile, " hr = %s%s(%s);\n",
szAutomationMethodPrefix,
(LPCSTR)szfn,
fIsSet ? "v" : "p" );
}
fprintf ( fpHDLFile, " if ( hr )\n return hr;\n" );
}
if ( fIsSet && pChildToken -> IsSet ( PROPERTY_SETDESIGNMODE ) )
{
fprintf ( fpHDLFile, " if ( !IsDesignMode() )\n return SetErrorInfo(CTL_E_SETNOTSUPPORTEDATRUNTIME);\n" );
}
if ( szAType == "VARIANT" )
{
fprintf ( fpHDLFile, " return SetErrorInfo(s_propdesc%s%s.a.Handle%sProperty(%s, %s, this, CVOID_CAST%s));\n}\n",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ),
(LPCSTR)szHandler,
(LPCSTR)szHandlerArgs,
fIsSet ? "&v" : "p",
(LPCSTR)szOffsetOf );
}
else if ( pChildToken -> IsSet ( PROPERTY_SUBOBJECT ) )
{
fprintf ( fpHDLFile, " return %s::CreateSubObject ( GetElementPtr(), (PROPERTYDESC *)&s_propdesc%s%s,\n ",
(LPCSTR)pChildToken->GetTagValue ( PROPERTY_SUBOBJECT ),
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ));
if ( pChildToken -> IsSet ( PROPERTY_PARAM1 ) )
{
fprintf ( fpHDLFile, "%s, ",
(LPCSTR)pChildToken->GetTagValue ( PROPERTY_PARAM1 ) );
}
fprintf ( fpHDLFile, "p );\n}\n" );
}
else
{
if ( szHandler == "Num" || szHandler == "Enum" )
{
fprintf ( fpHDLFile," return s_propdesc%s%s.b.%sNumberProperty(%s, this, CVOID_CAST%s);\n}\n",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ),
(LPCSTR)szHandlerMethodPrefix,
fIsSet ? "v" : "p",
(LPCSTR)szOffsetOf );
}
else
{
fprintf ( fpHDLFile, " return s_propdesc%s%s.b.%s%sProperty(%s, this, CVOID_CAST%s);\n}\n",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ),
(LPCSTR)szHandlerMethodPrefix,
(LPCSTR)szHandler,
fIsSet ? "v" : "p",
(LPCSTR)szOffsetOf );
}
}
}
void CPDLParser::GenerateCPPEnumDefs ( void )
{
Token *pToken;
char *pEValText;
// Only generate def's for this file
CTokenListWalker TokenList ( pRuntimeList, _pszPDLFileName );
fprintf ( fpHDLFile, "\n#ifndef _PROPDESCS_EXTERNAL\n\n" );
// Generate propdescs for every property token in every class ( in this file )
while ( pToken = TokenList.GetNext( TYPE_ENUM ) )
{
fprintf ( fpHDLFile, "EXTERN_C const ENUMDESC s_enumdesc%s = \n{ %u, %u, {\n",
pToken->GetTagValue ( ENUM_NAME ) ,
pToken->GetChildTokenCount(),
pToken->uEnumMask );
CTokenListWalker ChildList ( pToken );
while ( pToken = ChildList.GetNext() )
{
// If a string is specified use it
if ( pToken->IsSet ( EVAL_STRING ) )
{
pEValText = pToken->GetTagValue ( EVAL_STRING );
}
else
{
pEValText = pToken->GetTagValue ( EVAL_NAME );
}
fprintf ( fpHDLFile, " { _T(\"%s\"),%s},\n",
pEValText,
pToken->GetTagValue ( EVAL_VALUE ) );
}
fprintf ( fpHDLFile, "} };\n\n" );
}
fprintf ( fpHDLFile, "#endif // _PROPDESCS_EXTERNAL\n" );
}
void CPDLParser::GenerateInterfaceDISPIDs ( void )
{
Token *pInterfaceToken;
Token *pChildToken;
CString szName;
// Generate DISPID's for all interface methods that are not
// ref'd to a class
// Only generate def's for this file
CTokenListWalker TokenList ( pRuntimeList, _pszPDLFileName );
while ( pInterfaceToken = TokenList.GetNext( TYPE_INTERFACE ) )
{
szName = pInterfaceToken->GetTagValue ( INTERFACE_NAME );
if ( szName == "IDispatch" )
continue;
fprintf ( fpHDLFile, "// DISPIDs for class%s\n\n",
(LPCSTR)pInterfaceToken->GetTagValue ( INTERFACE_NAME ) );
CTokenListWalker ChildList ( pInterfaceToken );
while ( pChildToken = ChildList.GetNext() )
{
if ( pChildToken -> GetType() == TYPE_METHOD &&
!strlen( pChildToken -> GetTagValue ( METHOD_REFDTOCLASS ) ) &&
pChildToken -> IsSet ( METHOD_DISPID ) )
{
Token *pChildMatch = NULL;
CString szClassName;
Token *pClass;
szClassName = pInterfaceToken -> GetTagValue( METHOD_REFDTOCLASS );
pClass = FindClass ( szClassName );
if (pClass)
{
if (pChildToken->IsSet(METHOD_NOPROPDESC))
{
pChildMatch = FindMatchingEntryWOPropDesc(pClass, pChildToken);
}
}
if (!pChildMatch)
pChildMatch = pChildToken;
fprintf ( fpHDLFile, "#define DISPID_%s_%s %s\n",
(LPCSTR)pInterfaceToken->GetTagValue ( INTERFACE_NAME ),
(LPCSTR)pChildMatch->GetTagValue ( METHOD_NAME ),
(LPCSTR)pChildMatch->GetTagValue ( METHOD_DISPID ) );
}
}
}
}
void CPDLParser::GenerateEventDISPIDs ( FILE *fp, BOOL fPutDIID )
{
Token *pEventToken;
Token *pChildToken;
CString szName,szDISPName;
int i,nLength;
BOOL fPutComment;
// Generate DISPID's for all interface methods that are not
// ref'd to a class
// Only generate def's for this file
CTokenListWalker TokenList ( pRuntimeList, _pszPDLFileName );
while ( pEventToken = TokenList.GetNext( TYPE_EVENT ) )
{
szName = pEventToken->GetTagValue ( EVENT_NAME );
if ( szName == "IDispatch" || szName == "IUnknown" )
continue;
szName.ToUpper();
fPutComment = FALSE;
CTokenListWalker ChildList ( pEventToken );
while ( pChildToken = ChildList.GetNext() )
{
if ( pChildToken -> GetType() == TYPE_METHOD &&
!strlen( pChildToken -> GetTagValue ( METHOD_REFDTOCLASS ) ) &&
pChildToken -> IsSet ( METHOD_DISPID ) )
{
if ( !fPutComment )
{
fprintf ( fp, "// DISPIDs for event set %s\n\n",
(LPCSTR)pEventToken->GetTagValue ( EVENT_NAME ) );
fPutComment = TRUE;
}
szDISPName = pChildToken->GetTagValue ( METHOD_NAME );
szDISPName.ToUpper();
fprintf ( fp, "#define DISPID_%s_%s ",
(LPCSTR)szName,
(LPCSTR)szDISPName );
for ( i = 0, nLength = max ( 0, 49-szDISPName.Length()-szName.Length() ); i < nLength ; i++ )
{
fprintf ( fp, " " );
}
fprintf ( fp, "%s\n",
(LPCSTR)pChildToken->GetTagValue ( METHOD_DISPID ) );
}
}
if ( fPutDIID )
{
fprintf ( fp, "\nEXTERN_C const GUID DIID_%s;\n",
pEventToken->GetTagValue ( EVENT_NAME ));
}
if ( fPutComment )
fprintf ( fp, "\n" );
}
}
void CPDLParser::GenerateExternalInterfaceDISPIDs ( void )
{
Token *pInterfaceToken;
Token *pChildToken;
CString szName,szDISPName;
int i,nLength;
BOOL fPutComment;
// Generate DISPID's for all interface methods that are not
// ref'd to a class
// Only generate def's for this file
CTokenListWalker TokenList ( pRuntimeList, _pszPDLFileName );
while ( pInterfaceToken = TokenList.GetNext( TYPE_INTERFACE ) )
{
szName = pInterfaceToken->GetTagValue ( INTERFACE_NAME );
if ( szName == "IDispatch" || szName == "IUnknown" )
continue;
szName.ToUpper();
fPutComment = FALSE;
CTokenListWalker ChildList ( pInterfaceToken );
while ( pChildToken = ChildList.GetNext() )
{
Token *pChildMatch = NULL;
CString szClassName;
Token *pClass;
if ( !fPutComment )
{
fprintf ( fpDISPIDFile, "// DISPIDs for interface %s\n\n",
(LPCSTR)pInterfaceToken->GetTagValue ( INTERFACE_NAME ) );
fPutComment = TRUE;
}
if ( pChildToken -> GetType() == TYPE_METHOD )
{
szDISPName = pChildToken->GetTagValue ( METHOD_NAME );
szClassName = pChildToken -> GetTagValue( METHOD_REFDTOCLASS );
pClass = FindClass ( szClassName );
if (pClass)
{
if (pChildToken->IsSet(METHOD_NOPROPDESC))
{
if (pChildToken->IsSet(METHOD_SZINTERFACEEXPOSE))
szDISPName = pChildToken->GetTagValue(METHOD_SZINTERFACEEXPOSE);
pChildMatch = FindMatchingEntryWOPropDesc(pClass, pChildToken);
}
}
if (!pChildMatch)
pChildMatch = pChildToken;
}
else
{
// Property
szDISPName = pChildToken->GetTagValue ( PROPERTY_NAME );
szClassName = pChildToken -> GetTagValue( PROPERTY_REFDTOCLASS );
pClass = FindClass ( szClassName );
if (pClass)
{
if (pChildToken->IsSet(PROPERTY_NOPROPDESC))
{
if (pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE))
szDISPName = pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE);
pChildMatch = FindMatchingEntryWOPropDesc(pClass, pChildToken);
}
}
if (!pChildMatch)
pChildMatch = pChildToken;
}
szDISPName.ToUpper();
fprintf ( fpDISPIDFile, "#define DISPID_%s_%s ",
(LPCSTR)szName,
(LPCSTR)szDISPName );
for ( i = 0, nLength = max ( 0, 49-szDISPName.Length()-szName.Length() ); i < nLength ; i++ )
{
fprintf ( fpDISPIDFile, " " );
}
fprintf ( fpDISPIDFile, "%s\n",
(LPCSTR)pChildMatch->GetTagValue ( PROPERTY_DISPID ) );
}
if ( fPutComment )
fprintf ( fpDISPIDFile, "\n" );
}
}
void CPDLParser::GenerateClassDISPIDs ( void )
{
Token *pClassToken;
Token *pChildToken;
CString szCoClassName;
// Only generate def's for this file
CTokenListWalker TokenList ( pRuntimeList, _pszPDLFileName );
// Generate propdescs for every property token in every class ( in this file )
while ( pClassToken = TokenList.GetNext( TYPE_CLASS ) )
{
fprintf ( fpHDLFile, "// DISPIDs for class %s\n\n", (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ) );
if ( pClassToken -> IsSet ( CLASS_GUID ) )
{
pClassToken -> GetTagValueOrDefault ( szCoClassName,
CLASS_COCLASSNAME, pClassToken -> GetTagValue ( CLASS_NAME ) );
fprintf ( fpHDLFile, "EXTERN_C const GUID CLSID_%s;\n",
(LPCSTR)szCoClassName );
}
CTokenListWalker ChildList ( pClassToken );
while ( pChildToken = ChildList.GetNext() )
{
Token *pChildMatch = pChildToken;
if ( pChildMatch->nType == TYPE_PROPERTY && pChildMatch->IsSet ( PROPERTY_DISPID ) )
{
if (pChildMatch->IsSet(PROPERTY_NOPROPDESC))
{
pChildMatch = FindMatchingEntryWOPropDesc(pClassToken, pChildMatch);
if (!pChildMatch)
pChildMatch = pChildToken;
}
fprintf ( fpHDLFile, "#define DISPID_%s_%s %s\n",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChildMatch->GetTagValue ( PROPERTY_NAME ),
(LPCSTR)pChildMatch->GetTagValue ( PROPERTY_DISPID ) );
}
else if ( pChildMatch->nType == TYPE_METHOD && pChildMatch->IsSet ( METHOD_DISPID ) )
{
if (pChildMatch->IsSet(METHOD_NOPROPDESC))
{
pChildMatch = FindMatchingEntryWOPropDesc(pClassToken, pChildMatch);
if (!pChildMatch)
pChildMatch = pChildToken;
}
fprintf ( fpHDLFile, "#define DISPID_%s_%s %s\n",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChildMatch->GetTagValue ( METHOD_NAME ),
(LPCSTR)pChildMatch->GetTagValue ( METHOD_DISPID ) );
}
}
}
}
void CPDLParser::GeneratePropdescExtern ( Token *pClassToken, BOOL fRecurse )
{
Token *pChild;
Token *pSuperClassToken;
CTokenListWalker ChildList ( pClassToken );
// Add the supers definitions first. Recurse to the super of this super!!
// Notice that the fRecurse if used by abstract classes to only extern the
// PropertyDesc which are generated for the actual class.
pSuperClassToken = fRecurse ? GetSuperClassTokenPtr ( pClassToken ) : NULL;
if ( pSuperClassToken )
GeneratePropdescExtern ( pSuperClassToken );
// Don't generate any EXTERN_C for abstract class reference. The EXTERN_C
// is only in the hdl that contains both the PROPERTYDESC the EXTERN_C for
// the abstract class (e.g., bodyroot.hdl).
if ( fRecurse && pClassToken -> IsSet ( CLASS_ABSTRACT ) )
return;
fprintf ( fpHeaderFile, "\n#ifndef _%s_PROPDESCS_\n", pClassToken -> GetTagValue ( CLASS_NAME ) );
// Walk the super class propdescs looking for properties
while ( pChild = ChildList.GetNext() )
{
if ( pChild->GetType() == TYPE_PROPERTY )
{
StorageType stHowStored;
CString szHandler;
CString szFnPrefix;
szHandler = "";
szFnPrefix = "";
// Check for missing handler later
GetTypeDetails ( pChild->GetTagValue ( PROPERTY_TYPE ),
szHandler, szFnPrefix, &stHowStored );
if ( !ComputePROPDESC_STRUCT ( fpHeaderFile, pClassToken, pChild, szHandler, szFnPrefix ) )
return; // Bad error reported...leave
fprintf ( fpHeaderFile, " s_propdesc%s%s;\n",
pClassToken -> GetTagValue ( CLASS_NAME ),
pChild -> GetTagValue ( PROPERTY_NAME ) );
}
else if ( pChild->GetType() == TYPE_METHOD )
{
fprintf ( fpHeaderFile, "EXTERN_C const PROPERTYDESC_METHOD s_methdesc%s%s;\n",
pClassToken -> GetTagValue ( CLASS_NAME ),
pChild -> GetTagValue ( METHOD_NAME ) );
}
}
fprintf ( fpHeaderFile, "\n#endif\n" );
}
BOOL CPDLParser::GeneratePropdescReference ( Token *pClassToken,
BOOL fDerivedClass,
PropdescInfo *pPI,
int *pnPI,
BOOL &bHookToCElement,
int *pnSharedEntries )
{
Token *pChild;
if (!pClassToken)
return TRUE;
CTokenListWalker ChildList ( pClassToken );
// If the class superclass if CElement, we want to hook to CElement's hash table
// If this is not the case, we want to do what we used to do and repeat
// the super class properties in the subclasses.
if(GetSuperClassTokenPtr ( pClassToken ) &&
(strcmp(GetSuperClassTokenPtr ( pClassToken ) ->GetTagValue ( CLASS_NAME ),
"CElement") == 0))
{
bHookToCElement = TRUE;
}
if ( !GeneratePropdescReference ( GetSuperClassTokenPtr ( pClassToken ),
FALSE, pPI, pnPI,
bHookToCElement, pnSharedEntries ) )
{
return FALSE;
}
if (fDerivedClass)
{
ChildList.Reset();
}
// Walk the super class propdescs looking for properties
while ( pChild = ChildList.GetNext() )
{
if ( pChild->GetType() == TYPE_PROPERTY )
{
if ( !pChild->IsSet ( PROPERTY_INTERNAL ) && !pChild->IsSet ( PROPERTY_ABSTRACT ) &&
!pChild->IsSet( PROPERTY_NOPROPDESC ) &&
(!pChild->IsSet ( PROPERTY_NOPERSIST ) ||
( pChild->IsSet ( PROPERTY_NOPERSIST ) && pClassToken->IsSet( CLASS_KEEPNOPERSIST ) ) ) )
{
if(bHookToCElement && (strcmp(pClassToken -> GetTagValue ( CLASS_NAME ), "CElement") == 0))
{
*pnSharedEntries += 1;
}
else
{
pPI[*pnPI].Set(pClassToken -> GetTagValue ( CLASS_NAME ),
pChild -> GetTagValue ( PROPERTY_NAME ) ,
fDerivedClass,
pChild->GetTagValue ( PROPERTY_SZATTRIBUTE ),
PDLPARSE_BELONGSTOPARSE);
*pnPI += 1;
}
}
}
}
return TRUE;
}
BOOL CPDLParser::GenerateCPC ( Token *pThisClassToken)
{
if ( IsUniqueCPC ( pThisClassToken ) )
{
fprintf ( fpHDLFile, "\nconst CONNECTION_POINT_INFO %s::s_acpi[] = {\n",
pThisClassToken -> GetTagValue ( CLASS_NAME ) );
fprintf ( fpHDLFile, " CPI_ENTRY(IID_IPropertyNotifySink, DISPID_A_PROPNOTIFYSINK)\n" );
fprintf ( fpHDLFile, " CPI_ENTRY(DIID_%s, DISPID_A_EVENTSINK)\n",
pThisClassToken->GetTagValue( CLASS_EVENTS ) );
if (pThisClassToken->IsSet(CLASS_NONPRIMARYEVENTS1))
{
fprintf(fpHDLFile, " CPI_ENTRY(DIID_%s, DISPID_A_EVENTSINK)\n",
pThisClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS1));
}
if (pThisClassToken->IsSet(CLASS_NONPRIMARYEVENTS2))
{
fprintf(fpHDLFile, " CPI_ENTRY(DIID_%s, DISPID_A_EVENTSINK)\n",
pThisClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS2));
}
if (pThisClassToken->IsSet(CLASS_NONPRIMARYEVENTS3))
{
fprintf(fpHDLFile, " CPI_ENTRY(DIID_%s, DISPID_A_EVENTSINK)\n",
pThisClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS3));
}
if (pThisClassToken->IsSet(CLASS_NONPRIMARYEVENTS4))
{
fprintf(fpHDLFile, " CPI_ENTRY(DIID_%s, DISPID_A_EVENTSINK)\n",
pThisClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS4));
}
fprintf ( fpHDLFile, " CPI_ENTRY(IID_ITridentEventSink, DISPID_A_EVENTSINK)\n" );
fprintf ( fpHDLFile, " CPI_ENTRY(IID_IDispatch, DISPID_A_EVENTSINK)\n" );
fprintf ( fpHDLFile, " CPI_ENTRY_NULL\n};\n" );
}
return TRUE;
}
#ifdef COMPLUS_SHIM
void
CPDLParser::GenComPlusInheritance (Token *pClass, CString & inheritanceCStr)
{
// Any other interface to expose in the coclass which is part of the primary
// interface?
CString primaryInterfCStr;
CTokenListWalker ChildWalker(pClass);
Token *pChildToken;
BOOL fFirstInterf;
// Get the primary interface, if one exists.
if (pClass->IsSet(CLASS_INTERFACE))
{
primaryInterfCStr = pClass->GetTagValue(CLASS_INTERFACE);
inheritanceCStr = "public ICOMCookie, public ";
inheritanceCStr += primaryInterfCStr;
inheritanceCStr += "COMPLUS";
fFirstInterf = FALSE;
}
else
{
inheritanceCStr = "";
fFirstInterf = TRUE;
}
while (pChildToken = ChildWalker.GetNext())
{
if (pChildToken->GetType() == TYPE_IMPLEMENTS)
{
Token *pInterf;
CString szInterface;
szInterface = pChildToken->GetTagValue(IMPLEMENTS_NAME);
pInterf = FindInterface(szInterface);
if (pInterf)
{
// Is the interface a local one if not then don't check, we
// only need to check where interfaces are actually used.
if (FindInterfaceLocally(szInterface))
{
// If the super isn't specified and it's not a primary interface
// then error the super is required for non-primary interfaces.
if (_stricmp((LPSTR)pClass->GetTagValue(CLASS_INTERFACE),
(LPSTR)pInterf->GetTagValue(INTERFACE_NAME)) &&
!pInterf->IsSet(INTERFACE_SUPER) &&
!IsPrimaryInterface(szInterface))
{
char szErrorText [ MAX_LINE_LEN+1 ];
sprintf(szErrorText, "Interface %s missing super key.\n",
(LPSTR)pInterf->GetTagValue(INTERFACE_NAME));
ReportError(szErrorText);
return;
}
}
// If an implements is a primary interface then don't inherit again we did that at the beginning.
if (primaryInterfCStr != szInterface)
{
if (fFirstInterf)
{
fFirstInterf = FALSE;
}
else
{
inheritanceCStr += ",";
}
inheritanceCStr += " public ";
inheritanceCStr += pInterf->GetTagValue(INTERFACE_NAME);
inheritanceCStr += "COMPLUS";
}
}
}
}
}
#endif // COMPLUS_SHIM
void
CPDLParser::GenerateVTableArray (Token *pThisClassToken, BOOL *pbHashTableExists )
{
Token *pDerivedClass;
PropdescInfo rgPI[400]; // Max. number of method/prop for interface.
int nPI = 0;
UINT uVTblIndex = 0;
CString szInterf;
Token *pInterf;
BOOL bHookToCElement = FALSE;
int nSharedEntries = 0;
*pbHashTableExists = FALSE;
// Abstract classes don't need the vtable unless they name is CElement
// TODO: Terry, Implement the shared keywork here.
if ( (pThisClassToken->IsSet ( CLASS_ABSTRACT )) &&
(_stricmp(pThisClassToken->GetTagValue(CLASS_NAME), "CElement") != 0))
return;
pDerivedClass = pThisClassToken;
GetInterf:
szInterf = pDerivedClass->GetTagValue(CLASS_INTERFACE);
// If no interface then use the super to find an interface.
if (!szInterf.Length())
{
CString szClass;
szClass = pDerivedClass -> GetTagValue ( CLASS_SUPER );
pDerivedClass = FindClass(szClass);
if (!pDerivedClass)
ReportError ( "Unknown class\n" );
goto GetInterf;
}
pInterf = FindInterface(szInterf);
if (pInterf || strcmp((LPCSTR)szInterf, "IDispatch") == 0)
{
#ifdef COMPLUS_SHIM
// ***TLL*** COM+: Not spitting COM+ proxies for internal.pdl and mshtmext.pdl need to do, shouldn't special case.
BOOL fInternalPDL = (_stricmp(_pszPDLFileName, "internal.pdl") == 0) || (_stricmp(_pszPDLFileName, "mshtmext.pdl") == 0);
// Do we have a real coclass w/ a real GUID?
if (pThisClassToken->IsSet(CLASS_GUID) &&
pThisClassToken->IsSet(CLASS_INTERFACE) && !fInternalPDL)
{
// Then let's do some COM+ work...
CString inheritDecl;
CString szClassName;
if (pThisClassToken->IsSet(CLASS_COCLASSNAME))
szClassName = pThisClassToken->GetTagValue(CLASS_COCLASSNAME);
else
szClassName = pThisClassToken->GetTagValue(CLASS_NAME);
// Window needs some special processing as this is how unmanaged code hooks to
// managed code.
if (szClassName == "HTMLWindow2")
{
fprintf(fpHComPlusFile, "[managed, com, uuid={FF6BF9BB-FF1B-348D-8C21-CE642A866E7F}] __interface ICOMPLUSHookWindow\n");
fprintf(fpHComPlusFile, "{\n");
fprintf(fpHComPlusFile, "public:\n");
fprintf(fpHComPlusFile, "\tvoid Init(unsigned int myThis);\n");
fprintf(fpHComPlusFile, "};\n\n");
}
// COM+ managed code:
fprintf(fpHComPlusFile, "[managed, coclass");
if (szClassName == "HTMLWindow2")
{
fprintf(fpHComPlusFile, " , uuid={D66BF9BF-FF1B-348D-8C21-CE642A866E7F}");
}
fprintf(fpHComPlusFile, "] class %sCOMPLUS", (LPCSTR)szClassName);
GenComPlusInheritance(pThisClassToken, inheritDecl);
if (inheritDecl.Length())
{
fprintf(fpHComPlusFile, " : %s", (LPCSTR)inheritDecl);
if (szClassName == "HTMLWindow2")
{
fprintf(fpHComPlusFile, ", private ICOMPLUSHookWindow");
}
fprintf(fpHComPlusFile, "\n{\n");
}
else
{
fprintf(fpHComPlusFile, "\n{\n");
}
fprintf(fpHComPlusFile, "private:\n");
fprintf(fpHComPlusFile, "\tunsigned int\t_myThis;\n\n");
fprintf(fpHComPlusFile, "public:\n");
fprintf(fpHComPlusFile, "\t%sCOMPLUS (unsigned int myThis)\n\t\t{ _myThis = myThis; }\n\n", (LPCSTR)szClassName);
fprintf(fpHComPlusFile, "\tunsigned int getCOMCookie()\n\t\t{ return _myThis; }\n\n");
if (szClassName == "HTMLWindow2")
{
fprintf(fpHComPlusFile, "\tHTMLWindow2COMPLUS ()\n");
fprintf(fpHComPlusFile, "\t\t{ _myThis = 0; }\n\n");
fprintf(fpHComPlusFile, "\tvoid Init(unsigned int myThis)\n\t\t{ _myThis = myThis; }\n\n");
}
}
#endif // COMPLUS_SHIM
CVTableHash VTableHash; // Special hashtable that aids in spitting out the hash table
// Add the parser properties to the PropdescInfo array
if(!GeneratePropdescReference(pThisClassToken, TRUE, rgPI, &nPI, bHookToCElement, &nSharedEntries ))
ReportError("Error Storing PropDescs in PROPDESC array in HashTable");
// Add the OM properties and methods to the PropdescInfo array
if (pInterf)
{
ComputeVTable( pThisClassToken,
pInterf,
FALSE,
rgPI,
&nPI,
&uVTblIndex,
&VTableHash,
bHookToCElement);
}
#ifdef COMPLUS_SHIM
if (pThisClassToken->IsSet(CLASS_GUID) &&
pThisClassToken->IsSet(CLASS_INTERFACE) && !fInternalPDL)
{
fprintf(fpHComPlusFile, "};\n\n\n");
}
#endif // COMPLUS_SHIM
// Number of entries in vtable array.
*pbHashTableExists = bHookToCElement || (nPI > 0);
// Write out the "style" mini-propdesc array if we are dealing with
// the element class. The reason we do this is because a parser and OM
// propdesc (both of which are different) resolve to the same entry in
// the hash table. Hence, we have to make a hack and have the name resolve
// to an array of propdescs.
if(strcmp(pThisClassToken->GetTagValue(CLASS_NAME), "CElement") == 0)
{
fprintf(fpHDLFile, "static const PROPERTYDESC *s_propdescCElementStyleArray [ ] = \n"
"{\n"
" (PROPERTYDESC *)&s_propdescCElementstyle,\n"
" (PROPERTYDESC *)&s_propdescCElementstyle_Str\n"
"};\n");
}
else if(strcmp(pThisClassToken->GetTagValue(CLASS_NAME), "CInput") == 0)
{
fprintf(fpHDLFile, "static const PROPERTYDESC *s_propdescCInputCheckedArray [ ] = \n"
"{\n"
" (PROPERTYDESC *)&s_propdescCInputchecked,\n"
" (PROPERTYDESC *)&s_propdescCInputdefaultChecked\n"
"};\n");
}
// Write out the hash table
// Convert the class to a Unicode string so that it works correctly
// with the hash table, which is Unicode.
WCHAR strUnicode[256];
int retVal =
MultiByteToWideChar(CP_ACP, 0, pThisClassToken->GetTagValue(CLASS_NAME),
256,
strUnicode, 256);
if(retVal == 0)
{
ReportError("Error: Unable to convert classname to a Unicode string");
return;
}
if(VTableHash.GetHashTableLength() > 1024)
{
ReportError("Error: Hash table size has grown beyond 10K. Find more bits!");
return;
}
if(VTableHash.ToFile(fpHDLFile,
strUnicode,
nSharedEntries) != S_OK)
{
ReportError("Error: Unable to write out hashtable");
return;
}
// Write out the Hash Table Aggregate
fprintf(fpHDLFile,
"const CPtrBagVTableAggregate %s::s_StringTableAggregate = {\n"
" {\n", pThisClassToken->GetTagValue(CLASS_NAME));
if(bHookToCElement)
fprintf(fpHDLFile, " (CPtrBagVTable *)&CElement::s_StringTable,\n");
// Every class aggregates to itself.
fprintf(fpHDLFile,
" (CPtrBagVTable *)&%s::s_StringTable,\n"
" NULL\n"
" }\n"
"};\n", pThisClassToken->GetTagValue(CLASS_NAME));
// Store away a special cache for the document
if(_stricmp(pThisClassToken->GetTagValue(CLASS_NAME), "COmWindowProxy") == 0)
{
DWORD index;
if(!VTableHash.GetIndex(_T("document"), &index))
{
ReportError("The document must exist in the COmWindowProxy");
return;
}
fprintf(fpHDLFile, "const VTABLEDESC * const COmWindowProxy::s_COmWindowProxyDocument = &s_AssocVTableCOmWindowProxy%d._VTableDesc;\n", index);
}
}
else
{
char szErrorText [ MAX_LINE_LEN+1 ];
sprintf( szErrorText, "Unknown interface %s\n", (LPCSTR) szInterf );
ReportError ( szErrorText );
}
}
void
CPDLParser::SortPropDescInfo (PropdescInfo *pPI, int cPDI)
{
int x, y, cc;
PropdescInfo pd;
//sort em
for (x = 0; x < cPDI - 1; ++x)
{
for (y = x; y < cPDI; ++y)
{
cc = _stricmp( pPI[x]._szSortKey, pPI[y]._szSortKey ); // API caveat
if (cc > 0)
{
memcpy(&pd, pPI + x, sizeof(pd));
memcpy(pPI + x, pPI + y, sizeof(pd));
memcpy(pPI + y, &pd, sizeof(pd));
}
}
}
}
BOOL
CPDLParser::ComputeVTable ( Token *pClass,
Token *pInterface,
BOOL fDerived,
PropdescInfo *pPI,
int *piPI,
UINT *pUVTblIdx,
CVTableHash *pVTableHash,
BOOL &bHookToCElement,
BOOL fNonPrimaryTearoff/*= FALSE*/ )
{
CString szSuperInterf;
Token *pChildToken;
int cFuncs = 0;
BOOL fProperty = FALSE;
int idxIIDPrimaryTearoff = -1;
int idxIID;
CString szInterface;
// Compute if this interface on the class is a primary interface tearoff.
if (!fNonPrimaryTearoff)
{
Token *pTearoff;
pTearoff = FindTearoff(pClass->GetTagValue(CLASS_NAME), pInterface->GetTagValue(INTERFACE_NAME));
if (pTearoff)
{
CString szInterface;
Token *pInterfaceToken;
szInterface = pTearoff->GetTagValue(TEAROFF_INTERFACE);
pInterfaceToken = FindInterface(szInterface);
// If primary interface is not derived from IDispatch then this
// interface and all derived interfaces (vtable layout) are separated
// not concatenated.
LPSTR szSuperPrimaryInterf = pInterfaceToken->GetTagValue(INTERFACE_SUPER);
if (szSuperPrimaryInterf && *szSuperPrimaryInterf)
fNonPrimaryTearoff = ((_stricmp(szSuperPrimaryInterf, "IDispatch") ||
(_stricmp(pClass->GetTagValue(CLASS_NAME), "CElement") == 0)));
else
{
fNonPrimaryTearoff = FALSE;
}
}
}
szInterface = pInterface->GetTagValue(INTERFACE_NAME);
// We want classes which have their primary interface IHTMLElement
// and are derived from CElement to hook to CElement
if((szInterface == "IHTMLElement") &&
(_stricmp(pClass->GetTagValue(CLASS_NAME), "CElement") != 0))
{
bHookToCElement = TRUE;
}
else
{
idxIID = FindAndAddIIDs(szInterface);
if (idxIID == -1)
{
ReportError("Problem with IID adding.\n");
return FALSE;
}
if (fNonPrimaryTearoff)
idxIIDPrimaryTearoff = idxIID;
szSuperInterf = pInterface->GetTagValue(INTERFACE_SUPER);
if (szSuperInterf && *szSuperInterf && szSuperInterf != "IDispatch")
{
Token *pSuperInterf;
pSuperInterf = FindInterface(szSuperInterf);
if (!pSuperInterf)
return FALSE;
if (!ComputeVTable(pClass,
pSuperInterf,
TRUE,
pPI,
piPI,
pUVTblIdx,
pVTableHash,
bHookToCElement,
fNonPrimaryTearoff))
return FALSE;
}
CTokenListWalker ChildList ( pInterface );
while ( pChildToken = ChildList.GetNext() )
{
UINT uIIDnVTbl;
cFuncs = 0;
if ( pChildToken -> GetType() == TYPE_PROPERTY )
{
fProperty = TRUE;
cFuncs = pChildToken -> IsSet ( PROPERTY_GET ) ? 1 : 0;
cFuncs += (pChildToken -> IsSet ( PROPERTY_SET ) ? 1 : 0);
if (pChildToken->IsSet(PROPERTY_NOPROPDESC))
goto AddInVTable;
}
else if ( pChildToken -> GetType() == TYPE_METHOD )
{
fProperty = FALSE;
cFuncs = 1;
if (pChildToken->IsSet(METHOD_NOPROPDESC))
goto AddInVTable;
}
else
{
ReportError ( "Unknown token type in ComputeVTable.\n" );
return FALSE;
}
// Compute vtable offset. If primary interface is a tearoff then set
// the offset and the idx into the IID table. Note, all indexes start
// at 1 (zero is reserved to imply classdesc primary interface).
uIIDnVTbl = fNonPrimaryTearoff ? (((idxIIDPrimaryTearoff + 1) << 8) | *pUVTblIdx) : *pUVTblIdx;
pPI[*piPI].SetVTable(pChildToken -> GetTagValue ( fProperty ? (int)PROPERTY_REFDTOCLASS : (int)METHOD_REFDTOCLASS ),
pChildToken -> GetTagValue ( fProperty ? (int)PROPERTY_NAME : (int)METHOD_NAME ),
FALSE, // Unused.
pChildToken -> GetTagValue ( PROPERTY_SZATTRIBUTE ),
uIIDnVTbl | PDLPARSE_BELONGSTOOM, // Computed IID/VTable where iidIdx might be zero for the primary interface.
fProperty,
idxIID, // Index of interface
pChildToken);
(*piPI)++;
AddInVTable:
(*pUVTblIdx) += cFuncs;
}
}
// Each derived interface of the primary tearoff is separated not a straight
// derivation.
if (fNonPrimaryTearoff && _stricmp(szInterface, "IHTMLDocument"))
*pUVTblIdx = 0;
// Top most interface?
if ( !fDerived )
{
// Now check for any other interfaces mentioned in the as implements in
// the class it is exposed in the coclass, that interface is a
// separately supported interface.
CTokenListWalker ChildWalker(pClass);
Token *pChildToken;
CString szInterface;
Token *pInterfToken;
while (pChildToken = ChildWalker.GetNext())
{
if (pChildToken->GetType() == TYPE_IMPLEMENTS)
{
*pUVTblIdx = 0; // implements always starts at 0 vtable offset.
szInterface = pChildToken->GetTagValue(IMPLEMENTS_NAME);
if(_stricmp(pInterface->GetTagValue(INTERFACE_NAME), szInterface) == 0)
continue;
// TODO: TerryLu - Need to add code here to recongize and handle
// shares. Currently, we hardcode the following interfaces
// as once which are shared and implemented by CElement directly
if (szInterface == "IHTMLElement6")
{
ReportError ( "Need to Add IHTMLElement6 in parser.cxx(ComputeVTable())" );
return FALSE;
}
if ( ((szInterface == "IHTMLElement") ||
(szInterface == "IHTMLElement2") ||
(szInterface == "IHTMLElement3") ||
(szInterface == "IHTMLElement4") ||
(szInterface == "IHTMLElement5") ) &&
((_stricmp(pClass->GetTagValue(CLASS_NAME), "CElement") != 0)) )
{
bHookToCElement = TRUE;
continue;
}
pInterfToken = FindInterface(szInterface);
if (pInterfToken)
{
if (!ComputeVTable(pClass,
pInterfToken,
TRUE,
pPI,
piPI,
pUVTblIdx,
pVTableHash,
bHookToCElement,
TRUE))
return FALSE;
}
}
}
// Output the vtable interface sorted by name.
for (int iVTbl = 0; iVTbl < *piPI; iVTbl++)
{
PropdescInfo *pPrevPropdescInfo;
// Convert the sort key to unicode since the HashTable is in Unicode
WCHAR strUnicode[256];
int retVal =
MultiByteToWideChar(CP_ACP, 0, pPI[iVTbl]._szSortKey,
256,
strUnicode, 256);
if(retVal == 0)
{
ReportError("Unable to convert class name to Unicode");
return FALSE;
}
// Change the style property to point to a special array
// of PropertyDescs if we are dealing with the CElement class
if((_stricmp(pPI[iVTbl]._szSortKey, "style") == 0) &&
(_stricmp(pClass->GetTagValue(CLASS_NAME), "CElement") == 0))
{
pPI[iVTbl]._szPropName = "StyleArray";
pPI[iVTbl]._uVTblIndex |= PDLPARSE_PROPDESCARRAY;
pPI[iVTbl]._uVTblIndex |= PDLPARSE_BELONGSTOBOTH;
}
else if((_stricmp(pPI[iVTbl]._szSortKey, "checked") == 0) &&
(_stricmp(pClass->GetTagValue(CLASS_NAME), "CInput") == 0))
// Change the checked property to point to a special array
// of PropertyDescs if we are dealing with the CInput class
{
pPI[iVTbl]._szPropName = "CheckedArray";
pPI[iVTbl]._uVTblIndex |= PDLPARSE_PROPDESCARRAY;
pPI[iVTbl]._uVTblIndex |= PDLPARSE_BELONGSTOBOTH;
}
// If the hash table entry was already set by the parser,
// make it a shared entry by the parser and OM.
pPrevPropdescInfo = (PropdescInfo *)pVTableHash->GetCi(strUnicode);
if(pPrevPropdescInfo)
{
// We cannot have two different properties map to the same name
// unless they are ones we already know about
if((_stricmp(pPrevPropdescInfo->_szPropName, pPI[iVTbl]._szPropName) != 0) &&
(_stricmp(pPI[iVTbl]._szSortKey, "checked") != 0) &&
(_stricmp(pPI[iVTbl]._szSortKey, "style") != 0))
{
ReportError("We cannot have two different properties map to the same name");
return FALSE;
}
pPI[iVTbl]._uVTblIndex |= PDLPARSE_BELONGSTOBOTH;
}
// Set the entry in the hash table
if(pVTableHash->SetCi(strUnicode,
&pPI[iVTbl]) != S_OK)
{
ReportError("Error: Unable to add Hash entry to table");
return FALSE;
}
#ifdef COMPLUS_SHIM
// ***TLL*** COM+: Not spitting COM+ proxies for internal.pdl and mshtmext.pdl need to do, shouldn't special case.
BOOL fInternalPDL = (_stricmp(_pszPDLFileName, "internal.pdl") == 0) || (_stricmp(_pszPDLFileName, "mshtmext.pdl") == 0);
// Output COM+ code, only real classes are exposed.
if (pClass->IsSet(CLASS_GUID) && pClass->IsSet(CLASS_INTERFACE) && !fInternalPDL)
{
GenComPlusDeclarations(pClass, pPI + iVTbl);
}
#endif // COMPLUS_SHIM
}
}
return TRUE;
}
#ifdef COMPLUS_SHIM
void
CPDLParser::GenComPlusMethodsInInterfaces(Token *pInterfaceToken, Token *pClass /* =NULL */)
{
Token *pChildToken;
CString szMethodName;
CString szPropertyName;
CString argCStr;
CString resultCStr;
CTokenListWalker ChildWalker(pInterfaceToken);
while (pChildToken = ChildWalker.GetNext())
{
if (pChildToken->GetType() == TYPE_METHOD)
{
// ***TLL*** Need to handle vararg arguments. [METHOD_VARARG]
if (pChildToken->IsSet(METHOD_NOPROPDESC) &&
pChildToken->IsSet(METHOD_SZINTERFACEEXPOSE))
{
szMethodName = pChildToken->GetTagValue(METHOD_SZINTERFACEEXPOSE);
}
else
{
szMethodName = pChildToken->GetTagValue(METHOD_NAME);
}
if (GenComPlusArgumentSignature(pChildToken, resultCStr, argCStr))
{
fprintf(fpHComPlusFile, "\t%s %s %s;\n",
(LPCSTR)resultCStr,
(LPCSTR)szMethodName,
(LPCSTR)argCStr);
}
}
else // Property
{
if (pChildToken->IsSet(PROPERTY_NOPROPDESC) &&
pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE))
{
szPropertyName = pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE);
}
else
{
szPropertyName = pChildToken->GetTagValue(PROPERTY_NAME);
}
if (pChildToken->IsSet(PROPERTY_SET))
{
// ***TLL*** COM+: What happens to displaybind, bindable, hidden, restricted, nonbrowsable, source.
if (GenComPlusArgumentSignature(pChildToken, resultCStr, argCStr, SetProperty))
{
fprintf(fpHComPlusFile, "\t%s %s %s;\n",
(LPCSTR)resultCStr,
(LPCSTR)szPropertyName,
(LPCSTR)argCStr);
}
}
if (pChildToken->IsSet(PROPERTY_GET))
{
// ***TLL*** COM+: What happens to displaybind, bindable, hidden, restricted, nonbrowsable, source.
if (GenComPlusArgumentSignature(pChildToken, resultCStr, argCStr, GetProperty))
{
fprintf(fpHComPlusFile, "\t%s %s %s;\n",
(LPCSTR)resultCStr,
(LPCSTR)szPropertyName,
(LPCSTR)argCStr);
}
}
}
}
}
void
CPDLParser::GenComPlusInterfaces(Token *pInterfaceToken, char* pszSuper)
{
CString szInterf;
Token *pSuperInterf;
#if 0
if (_stricmp("IHTMLStyle", pInterfaceToken->GetTagValue(NAME_TAG)) == 0)
__asm { int 3 };
#endif
if (!PrimaryTearoff(pInterfaceToken) && (!pszSuper || !*pszSuper))
ReportError("COM+: Interfaces w/o tearoff need super:IDispatch\n");
// ***TLL*** COM+: For now don't expose any IUnknown derived classes.
if (_stricmp(pszSuper, "IUnknown") == 0)
return;
// Is the super derived from IUnknown?
szInterf = pszSuper;
pSuperInterf = FindInterface(szInterf);
if (pSuperInterf)
{
if (_stricmp(pSuperInterf->GetTagValue(INTERFACE_SUPER), "IUnknown") == 0)
return;
}
// ***TLL*** End of comment section
if (pInterfaceToken->IsSet(INTERFACE_CUSTOM) && pszSuper && *pszSuper)
{
fprintf(fpHComPlusFile, "[managed, com] interface %sCOMPLUS : public ICOMCookie, public %sCOMPLUS\n{\npublic:\n",
pInterfaceToken->GetTagValue(NAME_TAG),
pszSuper);
}
else
{
if (PrimaryTearoff(pInterfaceToken))
{
fprintf(fpHComPlusFile, "[managed, com] interface %sCOMPLUS : public ICOMCookie \n{\npublic:\n",
pInterfaceToken->GetTagValue(NAME_TAG));
}
else
{
if (strcmp("IDispatch", pszSuper) == 0)
{
fprintf(fpHComPlusFile, "[managed, com] interface %sCOMPLUS : public ICOMCookie \n{\npublic:\n",
pInterfaceToken->GetTagValue(NAME_TAG));
}
else
{
fprintf(fpHComPlusFile, "[managed, com] interface %sCOMPLUS : public ICOMCookie, public %sCOMPLUS \n{\npublic:\n",
pInterfaceToken->GetTagValue(NAME_TAG), pszSuper);
}
}
}
// Fill in methods of interface:
GenComPlusMethodsInInterfaces(pInterfaceToken);
fprintf(fpHComPlusFile, "};\n\n");
}
void
CPDLParser::GenComPlusESI()
{
CTokenListWalker ThisFileList(pRuntimeList, _pszPDLFileName);
Token * pInterfaceToken;
Token * pEnumToken;
Token * pStructToken;
//
// Generate all the event interfaces
//
ThisFileList.Reset();
while (pInterfaceToken = ThisFileList.GetNext(TYPE_EVENT))
{
if (!pInterfaceToken->IsSet(EVENT_ABSTRACT) &&
pInterfaceToken->IsSet(EVENT_GUID))
{
// TODO: ***TLL*** Need to spit out event interfaces.
}
}
//
// Generate all the enumerators.
//
ThisFileList.Reset();
while (pEnumToken = ThisFileList.GetNext(TYPE_ENUM))
{
// TODO: ***TLL*** Need to spit out enums.
}
//
// Generate all the structs
//
ThisFileList.Reset();
while (pStructToken = ThisFileList.GetNext(TYPE_STRUCT))
{
// TODO: ***TLL*** Need to spit out structs.
}
//
// Generate all the non-abstract interfaces.
//
ThisFileList.Reset();
while ( pInterfaceToken = ThisFileList.GetNext(TYPE_INTERFACE))
{
if (!pInterfaceToken->IsSet(INTERFACE_ABSTRACT) &&
pInterfaceToken->IsSet(INTERFACE_GUID))
{
GenComPlusInterfaces(pInterfaceToken, pInterfaceToken->GetTagValue(INTERFACE_SUPER));
}
else if (!pInterfaceToken->IsSet(INTERFACE_ABSTRACT) &&
!pInterfaceToken->IsSet(INTERFACE_GUID))
{
// Generate a forward declare
CString szInterfaceName;
szInterfaceName = pInterfaceToken->GetTagValue(INTERFACE_NAME);
if (szInterfaceName != "IDispatch" && szInterfaceName != "IUnknown")
{
fprintf(fpHComPlusFile, "interface %sCOMPLUS;\n", pInterfaceToken->GetTagValue(NAME_TAG));
}
}
}
}
BOOL
CPDLParser::GenComPlusArgumentSignature(Token *pMethod, CString & resultCStr, CString & argCStr, PropertyType propType /* = NotProperty */)
{
BOOL fNameOnly;
LPCSTR pSimpleType;
char pComPlusType[128];
BOOL fRet = FALSE; // Assume don't want to expose method/property
resultCStr = "";
argCStr = "";
fNameOnly = _stricmp(pMethod->GetTagValue(METHOD_NOPROPDESC), "nameonly") == 0;
if (pMethod->GetType() == TYPE_METHOD && !fNameOnly)
{
CTokenListWalker ArgListWalker(pMethod);
BOOL fResultFound = FALSE;
CString szAutomationType;
Token *pArgToken;
int cAType;
while (pArgToken = ArgListWalker.GetNext())
{
if (pArgToken->IsSet(METHODARG_RETURNVALUE))
{
szAutomationType = pArgToken->IsSet(METHODARG_ATYPE) ?
pArgToken->GetTagValue(METHODARG_ATYPE) :
pArgToken->GetTagValue(METHODARG_TYPE);
cAType = szAutomationType.Length();
if (cAType && szAutomationType[cAType - 2] == '*')
{
szAutomationType.PutChar(cAType - 2, '\0');
}
else if (cAType && szAutomationType[cAType - 1] == '*')
{
szAutomationType.PutChar(cAType - 1, '\0');
}
#if 0
if (szAutomationType == "IHTMLControlElement")
__asm {int 3};
#endif
pSimpleType = ConvertType(szAutomationType, TRUE, &pComPlusType[0]);
resultCStr = pSimpleType ? pSimpleType : pComPlusType;
fResultFound = TRUE;
}
}
if (!fResultFound)
{
resultCStr = "void";
}
BOOL fFirst = TRUE;
int idx = 1;
char buffer[40];
argCStr = "(";
ArgListWalker.Reset();
while (pArgToken = ArgListWalker.GetNext())
{
if (!pArgToken->IsSet(METHODARG_RETURNVALUE))
{
if (!fFirst)
{
argCStr += ", ";
}
szAutomationType = pArgToken->GetTagValue(METHODARG_TYPE);
cAType = szAutomationType.Length();
if (cAType && szAutomationType[cAType - 1] == '*')
{
szAutomationType.PutChar(cAType - 1, '\0');
}
pSimpleType = ConvertType(szAutomationType, TRUE, &pComPlusType[0]);
argCStr += pSimpleType ? pSimpleType : pComPlusType;
argCStr += " param";
_itoa(idx++, buffer, 10);
argCStr += buffer;
}
fFirst = FALSE;
}
argCStr += ")";
fRet = TRUE;
}
else
{
// Property
CString szAutomationType;
int cAType;
fNameOnly = _stricmp(pMethod->GetTagValue(PROPERTY_NOPROPDESC), "nameonly") == 0;
szAutomationType = pMethod->GetTagValue(PROPERTY_ATYPE);
cAType = szAutomationType.Length();
if (szAutomationType[cAType - 1] == '*')
{
szAutomationType.PutChar(cAType - 1, '\0');
}
pSimpleType = ConvertType(szAutomationType, TRUE, &pComPlusType[0]);
if (propType == SetProperty && !fNameOnly )
{
resultCStr = "void";
argCStr = "(";
argCStr += pSimpleType ? pSimpleType : pComPlusType;
argCStr += " param1)";
fRet = TRUE;
}
if (propType == GetProperty && !fNameOnly)
{
resultCStr = pSimpleType ? pSimpleType : pComPlusType;
argCStr = "()";
fRet = TRUE;
}
}
return fRet;
}
void
CPDLParser::GenComPlusDeclarations(Token *pClass, PropdescInfo *pPI)
{
BOOL fNameOnly;
LPCSTR pSimpleType;
char pComPlusType[128];
int uIIDIdx;
int uVTblIdx;
CString szClassName;
szClassName = pClass->IsSet(CLASS_COCLASSNAME) ? pClass->GetTagValue(CLASS_COCLASSNAME) : pClass->GetTagValue(CLASS_NAME);
#if 0
//if (pPI->_pToken->GetType() == TYPE_METHOD && _stricmp("fireEvent", (LPSTR)pPI->_pToken->GetTagValue(METHOD_NAME)) == 0)
if (pPI->_pToken->GetType() == TYPE_PROPERTY && _stricmp("bookmarks", (LPSTR)pPI->_pToken->GetTagValue(PROPERTY_NAME)) == 0)
__asm {int 3};
#endif
uIIDIdx = pPI->_uIIDIndex + 1; // zero is reserved for error.
uVTblIdx = (((pPI->_uVTblIndex & 0x00ff) + 7) * 4);
fNameOnly = _stricmp(pPI->_pToken->GetTagValue(METHOD_NOPROPDESC), "nameonly") == 0;
if (pPI->_pToken->GetType() == TYPE_METHOD && !fNameOnly)
{
CTokenListWalker ArgListWalker(pPI->_pToken);
BOOL fResultFound = FALSE;
CString szAutomationType;
Token *pArgToken;
int cAType;
CString szTypesSig;
CString szArgsType;
int cArgs = 0;
int cRequiredArgs = 0;
char *pDefaultParams[MAX_ARGS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
char *pDefaultStrParams[MAX_ARGS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
BOOL fBSTRArg;
BOOL fVARIANTArg;
BOOL fObjectReturn = FALSE;
ParamType objectParam[MAX_ARGS] = { CPDLParser::None, CPDLParser::None, CPDLParser::None, CPDLParser::None, CPDLParser::None, CPDLParser::None, CPDLParser::None, CPDLParser::None };
while (pArgToken = ArgListWalker.GetNext())
{
if (pArgToken->IsSet(METHODARG_RETURNVALUE))
{
szAutomationType = pArgToken->IsSet(METHODARG_ATYPE) ?
pArgToken->GetTagValue(METHODARG_ATYPE) :
pArgToken->GetTagValue(METHODARG_TYPE);
cAType = szAutomationType.Length();
if (cAType && szAutomationType[cAType - 2] == '*')
{
szAutomationType.PutChar(cAType - 2, '\0');
fObjectReturn = szAutomationType != "Variant";
}
else if (cAType && szAutomationType[cAType - 1] == '*')
{
szAutomationType.PutChar(cAType - 1, '\0');
fObjectReturn = szAutomationType != "Variant";
}
pSimpleType = ConvertType(szAutomationType, TRUE, &pComPlusType[0]);
if (pSimpleType)
{
// IUknown or IDispatch return value is an unsigned int from CPThunks
if (_stricmp(pSimpleType, "Object") != 0)
{
// VARIANT_BOOL, int's, etc. returned are not objects.
fObjectReturn = FALSE;
}
}
fprintf(fpCComPlusFile, "%s\n", pSimpleType ? pSimpleType : pComPlusType);
if (!pSimpleType)
{
if (_stricmp(pComPlusType, "Object") == 0)
{
strcpy(pComPlusType, "unsigned int");
}
}
fprintf(fpHComPlusFile, "\t%s ", pSimpleType ? pSimpleType : pComPlusType);
fResultFound = TRUE;
}
}
if (!fResultFound)
{
fprintf(fpHComPlusFile, "\tvoid ");
fprintf(fpCComPlusFile, "void\n");
}
fprintf(fpCComPlusFile, "%sCOMPLUS::", (LPCSTR)szClassName);
// Method
fprintf(fpHComPlusFile, "\t%s (", pPI->_pToken->IsSet(METHOD_SZINTERFACEEXPOSE) ?
(LPSTR)pPI->_pToken->GetTagValue(METHOD_SZINTERFACEEXPOSE) :
(LPSTR)pPI->_pToken->GetTagValue(METHOD_NAME));
fprintf(fpCComPlusFile, "%s (", pPI->_pToken->IsSet(METHOD_SZINTERFACEEXPOSE) ?
(LPSTR)pPI->_pToken->GetTagValue(METHOD_SZINTERFACEEXPOSE) :
(LPSTR)pPI->_pToken->GetTagValue(METHOD_NAME));
BOOL fFirst = TRUE;
int idx = 1;
BOOL fAnyDynamicCasts = FALSE;
ArgListWalker.Reset();
while (pArgToken = ArgListWalker.GetNext())
{
if (!pArgToken->IsSet(METHODARG_RETURNVALUE))
{
if (!fFirst)
{
fprintf(fpHComPlusFile, ", ");
fprintf(fpCComPlusFile, ", ");
}
szAutomationType = pArgToken->GetTagValue(METHODARG_TYPE);
cAType = szAutomationType.Length();
if (cAType && szAutomationType[cAType - 1] == '*')
{
szAutomationType.PutChar(cAType - 1, '\0');
if (szAutomationType == "IUnknown" || szAutomationType == "IDispatch")
{
objectParam[idx - 1] = CPDLParser::AnyObject;
}
else if (szAutomationType != "Variant")
{
objectParam[idx - 1] = CPDLParser::Object;
}
}
pSimpleType = ConvertType(szAutomationType, TRUE, &pComPlusType[0]);
if (pSimpleType)
{
// IUknown or IDispatch return value is an unsigned int from CPThunks
if (_stricmp(pSimpleType, "Object") != 0)
{
// VARIANT_BOOL, int's, etc. returned are not objects.
objectParam[idx - 1] = CPDLParser::None;
}
}
fprintf(fpHComPlusFile, "%s param%i", pSimpleType ? pSimpleType : pComPlusType, idx);
fprintf(fpCComPlusFile, "%s param%i", pSimpleType ? pSimpleType : pComPlusType, idx++);
}
fFirst = FALSE;
}
fprintf(fpHComPlusFile, ");\n");
fprintf(fpCComPlusFile, ")\n");
fprintf(fpCComPlusFile, "{\n");
if (BuildMethodSignature(pPI->_pToken,
szTypesSig,
szArgsType,
fBSTRArg,
fVARIANTArg,
cArgs,
cRequiredArgs,
pDefaultParams,
pDefaultStrParams))
{
CString szFullSignature;
BOOL fAtLeastOne = FALSE;
int i;
if (fObjectReturn)
{
fprintf(fpCComPlusFile, "\tunsigned int myPDispatch;\n\n");
}
for (i = 0; i < cArgs; i++)
{
if (objectParam[i] & CPDLParser::GenericObject)
{
fprintf(fpCComPlusFile, "\tICOMCookie tempParam%i = dynamic_cast<ICOMCookie>(param%i);\n", i + 1, i + 1);
fAtLeastOne = TRUE;
}
}
if (fAtLeastOne)
{
fprintf(fpCComPlusFile, "\n");
}
// If no return value then set the retVal to void.
if (!szTypesSig[0])
{
szTypesSig = "void";
}
// If no arguments then set the argList to void.
if (!szArgsType[0])
{
szArgsType = "_void";
}
szTypesSig += szArgsType;
MakeSignature("Method", szTypesSig, szFullSignature);
if (fResultFound)
{
fprintf(fpCComPlusFile, "\t%s", fObjectReturn ? "myPDispatch = " : "return ");
}
else
{
fprintf(fpCComPlusFile, "\t");
}
fprintf(fpCComPlusFile, "CPThunks::COMPLUS_%s(_myThis, %i, %i", (LPCSTR)szFullSignature, uIIDIdx, uVTblIdx);
for (i = 0; i < cArgs; i++)
{
if (objectParam[i] & CPDLParser::GenericObject)
{
fprintf(fpCComPlusFile, ", tempParam%i.getCOMCookie()", i + 1);
}
else if (objectParam[i] & CPDLParser::Object)
{
fprintf(fpCComPlusFile, ", param%i.getCOMCookie()", i + 1);
}
else
{
fprintf(fpCComPlusFile, ", param%i", i + 1);
}
}
fprintf(fpCComPlusFile, ");\n");
}
if (fObjectReturn)
{
// ***TLL*** COM+: Need to create class for return value. For now just return 0.
// Should be something like "return new HTMLDOMNodeCOMPLUS(myPDispatch)" where HTMLDOMNodeCOMPLUS
// is a COM+ class.
if (fObjectReturn)
{
fprintf(fpCComPlusFile, "\n");
}
fprintf(fpCComPlusFile, "\treturn 0;\n");
}
fprintf(fpCComPlusFile, "}\n\n");
}
else
{
// Property
CString szAutomationType;
int cAType;
ParamType propertyParam = CPDLParser::None;
BOOL fInterfaceFound;
fNameOnly = _stricmp(pPI->_pToken->GetTagValue(PROPERTY_NOPROPDESC), "nameonly") == 0;
szAutomationType = pPI->_pToken->GetTagValue(PROPERTY_ATYPE);
cAType = szAutomationType.Length();
if (szAutomationType[cAType - 1] == '*')
{
szAutomationType.PutChar(cAType - 1, '\0');
}
if (cAType && szAutomationType[cAType - 1] == '*')
{
szAutomationType.PutChar(cAType - 1, '\0');
if (szAutomationType == "IUnknown" || szAutomationType == "IDispatch")
{
propertyParam = CPDLParser::AnyObject;
}
else if (szAutomationType != "Variant")
{
propertyParam = CPDLParser::Object;
}
}
pSimpleType = ConvertType(szAutomationType, TRUE, &pComPlusType[0], &fInterfaceFound);
if (pSimpleType)
{
// IUknown or IDispatch return value is an unsigned int from CPThunks
if (_stricmp(pSimpleType, "Object") != 0)
{
// VARIANT_BOOL, int's, etc. returned are not objects.
propertyParam = CPDLParser::None;
}
}
if (pPI->_pToken->IsSet(PROPERTY_SET) && !fNameOnly )
{
fprintf(fpHComPlusFile, "\tvoid\t%s (%s param1);\n",
pPI->_pToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
(LPSTR)pPI->_pToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
(LPSTR)pPI->_pToken->GetTagValue(PROPERTY_NAME),
pSimpleType ? pSimpleType : pComPlusType);
fprintf(fpCComPlusFile, "void\n%sCOMPLUS::%s (%s param1)\n",
(LPCSTR)szClassName,
pPI->_pToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
(LPSTR)pPI->_pToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
(LPSTR)pPI->_pToken->GetTagValue(PROPERTY_NAME),
pSimpleType ? pSimpleType : pComPlusType);
fprintf(fpCComPlusFile, "{\n");
if (pSimpleType)
{
if (_stricmp(pSimpleType, "String") == 0)
{
fprintf(fpCComPlusFile, "\tCPThunks::COMPLUS_S_String(_myThis, %i, %i, param1);\n", uIIDIdx, uVTblIdx);
}
else if (_stricmp(pSimpleType, "Object") == 0 )
{
fprintf(fpCComPlusFile, "\tunsigned int tempParam1 = dynamic_cast<ICOMCookie>(param1).getCOMCookie();\n");
fprintf(fpCComPlusFile, "\tCPThunks::COMPLUS_S_IDispatchp(_myThis, %i, %i, tempParam1);\n", pSimpleType, uIIDIdx, uVTblIdx);
}
else
{
fprintf(fpCComPlusFile, "\tCPThunks::COMPLUS_S_%s(_myThis, %i, %i, param1);\n", pSimpleType, uIIDIdx, uVTblIdx);
}
}
else if (fInterfaceFound)
{
fprintf(fpCComPlusFile, "\tCPThunks::COMPLUS_S_IDispatchp(_myThis, %i, %i, param1.getCOMCookie());\n", uIIDIdx, uVTblIdx);
}
else
{
fprintf(fpCComPlusFile, "\tCPThunks::COMPLUS_S_%s(_myThis, %i, %i, param1);\n", pComPlusType, uIIDIdx, uVTblIdx);
}
fprintf(fpCComPlusFile, "}\n\n");
}
if (pPI->_pToken->IsSet(PROPERTY_GET) && !fNameOnly)
{
fprintf(fpHComPlusFile, "\t%s\t%s ();\n",
pSimpleType ? pSimpleType : pComPlusType,
pPI->_pToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
(LPSTR)pPI->_pToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
(LPSTR)pPI->_pToken->GetTagValue(PROPERTY_NAME));
fprintf(fpCComPlusFile, "%s\n%sCOMPLUS::%s ()\n",
pSimpleType ? pSimpleType : pComPlusType,
(LPCSTR)szClassName,
pPI->_pToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
(LPSTR)pPI->_pToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
(LPSTR)pPI->_pToken->GetTagValue(PROPERTY_NAME));
fprintf(fpCComPlusFile, "{\n");
if (pSimpleType)
{
if (_stricmp(pSimpleType, "String") == 0)
{
fprintf(fpCComPlusFile, "\treturn CPThunks::COMPLUS_G_String(_myThis, %i, %i);\n", uIIDIdx, uVTblIdx + 1);
}
else if (_stricmp(pSimpleType, "Object") == 0)
{
// return IUnknown or IDispatch (not a qualified interface like IHTMLnnnnn).
fprintf(fpCComPlusFile, "\tunsigned int\tmyPDispatch;\n\n");
fprintf(fpCComPlusFile, "\tmyPDispatch = CPThunks::COMPLUS_G_%s(_myThis, %i, %i);\n", pSimpleType, uIIDIdx, uVTblIdx + 1);
//TODO: ***TLL*** COM+: Hook up document property of Window. Need generic mechanism here.
if (_stricmp((LPCSTR)szClassName, "HTMLWindow2") == 0)
{
if (_stricmp(pPI->_pToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
(LPSTR)pPI->_pToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
(LPSTR)pPI->_pToken->GetTagValue(PROPERTY_NAME),
"document") == 0)
{
fprintf(fpCComPlusFile, "return new HTMLDocumentCOMPLUS(myPDispatch);\n");
fprintf(fpCComPlusFile, "//"); // comment the next return spit out
}
}
// TODO: ***TLL*** COM+: Need to return (coclass) object stuffed myPDispatch. Remove return 0; and used below commented out line.
fprintf(fpCComPlusFile, "\treturn 0;\n");
// fprintf(fpCComPlusFile, "\treturn new %s(myPDispatch);\n", pComPlusType);
}
else
{
fprintf(fpCComPlusFile, "\treturn CPThunks::COMPLUS_G_%s(_myThis, %i, %i);\n", pSimpleType, uIIDIdx, uVTblIdx + 1);
}
}
else if (_stricmp(pComPlusType, "Variant") == 0)
{
fprintf(fpCComPlusFile, "\tunsigned int\tmyPVariant;\n\n");
fprintf(fpCComPlusFile, "\tmyPVariant = CPThunks::COMPLUS_G_%s(_myThis, %i, %i);\n\n", "VARIANT", uIIDIdx, uVTblIdx + 1);
fprintf(fpCComPlusFile, "\treturn new Variant(myPVariant);\n");
}
else
{
fprintf(fpCComPlusFile, "\tunsigned int\tmyPDispatch;\n\n");
fprintf(fpCComPlusFile, "\tmyPDispatch = CPThunks::COMPLUS_G_%s(_myThis, %i, %i);\n\n", "Object", uIIDIdx, uVTblIdx + 1);
//TODO: ***TLL*** COM+: Hook up document property of Window. Need generic mechanism here.
if (_stricmp((LPCSTR)szClassName, "HTMLWindow2") == 0)
{
if (_stricmp(pPI->_pToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
(LPSTR)pPI->_pToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
(LPSTR)pPI->_pToken->GetTagValue(PROPERTY_NAME),
"document") == 0)
{
fprintf(fpCComPlusFile, "return new HTMLDocumentCOMPLUS(myPDispatch);\n");
fprintf(fpCComPlusFile, "//"); // comment the next return spit out
}
}
// ***TLL*** COM+: Need to return (coclass) object stuffed myPDispatch. Remove return 0; and used below commented out line.
fprintf(fpCComPlusFile, "\treturn 0;\n");
// fprintf(fpCComPlusFile, "\treturn new %s(myPDispatch);\n", pComPlusType);
}
fprintf(fpCComPlusFile, "}\n\n");
}
}
}
#endif // COMPLUS_SHIM
BOOL
CPDLParser::ComputePROPDESC_STRUCT ( FILE *fp, Token *pClassToken, Token *pChild, CString & szHandler, CString & szFnPrefix )
{
char szErrorText [ MAX_LINE_LEN+1 ];
fprintf ( fp, "EXTERN_C const " );
if ( !pChild->IsSet ( PROPERTY_ABSTRACT ) && szHandler == "Num" || szHandler == "Enum" || szHandler == "UnitValue" )
{
// Numeric Handlers
if ( pChild->IsSet ( PROPERTY_GETSETMETHODS ) )
{
fprintf ( fp, "PROPERTYDESC_NUMPROP_GETSET" );
}
else if ( pChild->IsSet ( PROPERTY_ABSTRACT ) )
{
fprintf ( fp, "PROPERTYDESC_NUMPROP_ABSTRACT" );
}
else if ( pChild->IsSet ( PROPERTY_ENUMREF ) )
{
fprintf ( fp, "PROPERTYDESC_NUMPROP_ENUMREF" );
}
else
{
fprintf ( fp, "PROPERTYDESC_NUMPROP" );
}
}
else
{
// BASIC PROP PARAM Structure
if ( pChild->IsSet ( PROPERTY_GETSETMETHODS ) )
{
if ( szFnPrefix == "" )
{
sprintf ( szErrorText, "Invalid Type:%s in Class:%s Property:%s\n",
(LPCSTR)pChild->GetTagValue ( PROPERTY_TYPE ),
(LPCSTR)pClassToken->GetTagValue(CLASS_NAME),
(LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ) );
ReportError ( szErrorText );
return FALSE;
}
fprintf ( fp, "PROPERTYDESC_%s_GETSET", (LPCSTR)szFnPrefix );
}
else if ( pChild->IsSet ( PROPERTY_ABSTRACT ) )
{
fprintf ( fp, "PROPERTYDESC_BASIC_ABSTRACT" );
}
else
{
fprintf ( fp, "PROPERTYDESC_BASIC" );
}
}
return TRUE;
}
Token * CPDLParser::FindEnum ( Token *pChild )
{
// Get the enum mask from the enum named by PROPERTY_TYPE
CTokenListWalker WholeList ( pRuntimeList );
return WholeList.GetNext ( TYPE_ENUM, pChild->GetTagValue ( PROPERTY_TYPE ) );
}
char * CPDLParser::MapTypeToIDispatch ( CString & szType )
{
CString szHandler;
CString szFnPrefix;
char szStrType[255];
strcpy(szStrType, (LPCSTR)szType);
if (GetTypeDetails (szStrType, szHandler, szFnPrefix, NULL) && (szHandler == "object"))
{
int cSz = szType.Length();
if (szType[cSz - 1] == '*' && szType[cSz - 2] == '*')
{
// is it an IUnknown or an IDispatch?
if (_strnicmp(szType, "IUnknown", cSz-2)==0)
return "IUnknownpp";
else
return "IDispatchpp";
}
else if (szType[cSz - 1] == '*')
{
// is it an IUnknown or an IDispatch?
if (_strnicmp(szType, "IUnknown",cSz-1)==0)
return "IUnknownp";
else
return "IDispatchp";
}
}
return NULL;
}
Token * CPDLParser::FindEventMethod(Token *pClassToken, LPCSTR szEvent)
{
Token *pChildToken;
CTokenListWalker WholeList(pRuntimeList);
WholeList.Reset();
Token *pEventToken = WholeList.GetNext(TYPE_EVENT, pClassToken->GetTagValue(CLASS_EVENTS));
if (pEventToken)
{
CTokenListWalker ChildList(pEventToken);
while (pChildToken = ChildList.GetNext())
{
if (_stricmp(pChildToken->GetTagValue(METHOD_NAME), szEvent) == 0)
return pChildToken;
}
}
WholeList.Reset();
pEventToken = WholeList.GetNext(TYPE_EVENT, pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS1));
if (!pEventToken)
return NULL;
{
CTokenListWalker ChildList(pEventToken);
while (pChildToken = ChildList.GetNext())
{
if (_stricmp(pChildToken->GetTagValue(METHOD_NAME), szEvent) == 0)
return pChildToken;
}
}
WholeList.Reset();
pEventToken = WholeList.GetNext(TYPE_EVENT, pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS2));
if (!pEventToken)
return NULL;
{
CTokenListWalker ChildList(pEventToken);
while (pChildToken = ChildList.GetNext())
{
if (_stricmp(pChildToken->GetTagValue(METHOD_NAME), szEvent) == 0)
return pChildToken;
}
}
WholeList.Reset();
pEventToken = WholeList.GetNext(TYPE_EVENT, pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS3));
if (!pEventToken)
return NULL;
{
CTokenListWalker ChildList(pEventToken);
while (pChildToken = ChildList.GetNext())
{
if (_stricmp(pChildToken->GetTagValue(METHOD_NAME), szEvent) == 0)
return pChildToken;
}
}
WholeList.Reset();
pEventToken = WholeList.GetNext(TYPE_EVENT, pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS4));
if (!pEventToken)
return NULL;
{
CTokenListWalker ChildList(pEventToken);
while (pChildToken = ChildList.GetNext())
{
if (_stricmp(pChildToken->GetTagValue(METHOD_NAME), szEvent) == 0)
return pChildToken;
}
}
return NULL;
}
Token * CPDLParser::FindEventProp(Token *pClassToken, LPCSTR szEvent)
{
Token *pChild;
CTokenListWalker ChildList ( pClassToken );
while ( pChild = ChildList.GetNext() )
{
if ( pChild->nType == TYPE_PROPERTY &&
pChild->IsSet(PROPERTY_SCRIPTLET) &&
_stricmp(pChild->GetTagValue(PROPERTY_NAME), szEvent) == 0 )
return pChild;
}
return NULL;
}
BOOL CPDLParser::ComputeProperty ( Token *pClassToken, Token *pChild )
{
CString szClass;
CString szHandler;
CString szFnPrefix;
CString szHTMLName;
char szExposedName [ MAX_LINE_LEN+1 ];
CString szdwFlags;
CString szNotPresentDefault;
CString szNotAssignedDefault;
CString szUpperName;
CString szDispid;
char szErrorText [ MAX_LINE_LEN+1 ];
StorageType stHowStored;
const CCachedAttrArrayInfo *pCAAI = NULL;
BOOL fNumericHandler;
CString szVTDef;
CString szPropSignature;
CString szPropVT;
Token *pEnumType;
Token *pEventChild = NULL;
char chCustomInvokeIdx[128];
char *pDispatchType;
CString szPreText,szPostText;
CString szMemberDesc;
szPreText = "_T(";
szPostText = ")";
pEnumType = FindEnum ( pChild );
if ( pEnumType )
{
// Generic enumerator property handler, the propDesc has the enumerator
// type.
szPropVT = "PropEnum";
}
else
{
char *pWS;
szPropVT = pChild->GetTagValue ( PROPERTY_ATYPE );
// Remove any underscores in the type name.
while ((pWS = szPropVT.FindChar('_')))
{
while (*pWS = *(pWS + 1))
pWS++;
*pWS = '\0';
}
}
// Should this type be mapped to IDispatch?
pDispatchType = MapTypeToIDispatch ( szPropVT );
if (pDispatchType)
{
szPropVT = pDispatchType;
}
szClass = pClassToken->GetTagValue ( CLASS_NAME );
szUpperName = pChild->GetTagValue ( PROPERTY_NAME );
szUpperName.ToUpper();
szHandler = "";
szFnPrefix = "";
// Check for missing handler later
GetTypeDetails ( pChild->GetTagValue ( PROPERTY_TYPE ),
szHandler, szFnPrefix, &stHowStored );
CString szPropParamDesc;
szdwFlags = pChild->GetTagValue ( PROPERTY_DWFLAGS );
if ( pChild->IsSet ( PROPERTY_GETSETMETHODS ) )
{
szPropParamDesc = "PROPPARAM_GETMFHandler | PROPPARAM_SETMFHandler";
szPropSignature = "GS";
}
else if ( pChild->IsSet ( PROPERTY_MEMBER ) )
{
szPropParamDesc = "PROPPARAM_MEMBER";
}
else
{
szPropParamDesc = "";
}
if ( pChild->IsSet ( PROPERTY_GET ) )
{
szPropSignature = "G";
if ( szPropParamDesc [ 0 ] )
szPropParamDesc += " | ";
szPropParamDesc += "PROPPARAM_INVOKEGet";
}
if ( pChild->IsSet ( PROPERTY_SET ) )
{
szPropSignature += "S";
if ( szPropParamDesc [ 0 ] )
szPropParamDesc += " | ";
szPropParamDesc += "PROPPARAM_INVOKESet";
}
if (!szPropSignature[0])
{
szPropSignature = "GS";
if ( szPropParamDesc [ 0 ] )
szPropParamDesc += " | ";
szPropParamDesc += "PROPPARAM_INVOKEGet | PROPPARAM_INVOKESet";
}
// Write out the function signature for this property.
if ( !FindAndAddSignature ( szPropSignature, szPropVT, &chCustomInvokeIdx[0] ) )
return FALSE;
if ( pChild->IsSet ( PROPERTY_PPFLAGS ))
{
szPropParamDesc += " | ";
szPropParamDesc += pChild->GetTagValue ( PROPERTY_PPFLAGS );
}
if ( pChild->IsSet ( PROPERTY_NOPERSIST ) )
{
szPropParamDesc += " | PROPPARAM_NOPERSIST";
}
if ( pChild->IsSet ( PROPERTY_INVALIDASNOASSIGN ) )
{
szPropParamDesc += " | PROPPARAM_INVALIDASNOASSIGN";
}
if ( pChild->IsSet ( PROPERTY_CUSTOMENUM ) )
{
szPropParamDesc += " | PROPPARAM_CUSTOMENUM ";
}
if ( pChild->IsSet ( PROPERTY_NOTPRESENTASDEFAULT ) )
{
szPropParamDesc += " | PROPPARAM_NOTPRESENTASDEFAULT";
}
if ( pChild->IsSet ( PROPERTY_HIDDEN ) )
{
szPropParamDesc += " | PROPPARAM_HIDDEN";
}
if ( pChild->IsSet ( PROPERTY_RESTRICTED ) )
{
szPropParamDesc += " | PROPPARAM_RESTRICTED";
}
if ( pChild->IsSet ( PROPERTY_CAA ) )
{
szDispid = pChild->GetTagValue( PROPERTY_DISPID );
pCAAI = GetCachedAttrArrayInfo(szDispid);
szPropParamDesc += " | PROPPARAM_ATTRARRAY ";
#if 0
if (pCAAI->szPPFlags)
{
szPropParamDesc += " | ";
szPropParamDesc += pCAAI->szPPFlags;
}
if (pCAAI->szLMinBitMask)
{
pChild->AddTag( PROPERTY_MIN , pCAAI->szLMinBitMask );
}
#endif
}
if ( pChild->IsSet ( PROPERTY_MINOUT ) )
{
szPropParamDesc += " | PROPPARAM_MINOUT";
}
if ( pChild->IsSet ( PROPERTY_SETDESIGNMODE ) )
{
szPropParamDesc += " | PROPPARAM_READONLYATRUNTIME";
}
// If we're processing a property that applies to a CF/PF/SF/FF, mark it here
// this helps us optimize the apply process. Only properties with a DISPID that
// matches our apply table, can be applied
if ( pCAAI && pCAAI->szDispId != NULL )
{
szPropParamDesc += " | PROPPARAM_STYLISTIC_PROPERTY";
}
if ( pChild -> IsSet ( PROPERTY_SCRIPTLET ) )
{
szPropParamDesc += " | PROPPARAM_SCRIPTLET";
pEventChild = FindEventMethod(pClassToken, pChild->GetTagValue(PROPERTY_NAME));
if (pEventChild)
{
if (pEventChild->IsSet(METHOD_CANCELABLE))
{
szPropParamDesc += " | PROPPARAM_CANCELABLE";
}
if (pEventChild->IsSet(METHOD_BUBBLING))
{
szPropParamDesc += " | PROPPARAM_BUBBLING";
}
}
else if (!pChild->IsSet(PROPERTY_NOPROPDESC) && !pChild->IsSet(PROPERTY_BASEIMPLEMENTATION))
{
sprintf ( szErrorText, "Unexpected Error:Event prop:%s in Class:%s not found in any Events interface defn.\n",
(LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ),
(LPCSTR)pClassToken->GetTagValue(CLASS_NAME) );
ReportError ( szErrorText );
return FALSE;
}
}
szMemberDesc = "";
if ( pChild->IsSet ( PROPERTY_CAA ) )
{
if ( pCAAI->dwFlags & CCSSF_CLEARCACHES )
{
// Always add dwFlags:ELEMCHNG_CLEARCACHES for these properties
if ( szdwFlags [0] )
{
szdwFlags += "|";
}
else
{
szdwFlags = "";
}
szdwFlags+="ELEMCHNG_CLEARCACHES";
}
if ( pCAAI->dwFlags & CCSSF_CLEARFF )
{
// Always add dwFlags:ELEMCHNG_CLEARFF for these properties
if ( szdwFlags [0] )
{
szdwFlags += "|";
}
else
{
szdwFlags = "";
}
szdwFlags+="ELEMCHNG_CLEARFF";
}
if ( pCAAI->dwFlags & CCSSF_REMEASURECONTENTS )
{
// Always add dwFlags:ELEMCHNG_REMEASURECONTENTS for these properties
if ( szdwFlags [0] )
{
szdwFlags += "|";
}
else
{
szdwFlags = "";
}
szdwFlags+="ELEMCHNG_REMEASURECONTENTS";
}
if ( pCAAI->dwFlags & CCSSF_REMEASUREALLCONTENTS )
{
// Always add dwFlags:ELEMCHNG_REMEASURECONTENTS for these properties
if ( szdwFlags [0] )
{
szdwFlags += "|";
}
else
{
szdwFlags = "";
}
szdwFlags+="ELEMCHNG_REMEASUREALLCONTENTS";
}
if ( pCAAI->dwFlags & CCSSF_REMEASUREINPARENT )
{
// Always add dwFlags:ELEMCHNG_REMEASUREINPARENT for these properties
if ( szdwFlags [0] )
{
szdwFlags += "|";
}
else
{
szdwFlags = "";
}
szdwFlags+="ELEMCHNG_REMEASUREINPARENT";
}
if ( pCAAI->dwFlags & CCSSF_SIZECHANGED )
{
// Always add dwFlags:ELEMCHNG_SIZECHANGED for these properties
if ( szdwFlags [0] )
{
szdwFlags += "|";
}
else
{
szdwFlags = "";
}
szdwFlags+="ELEMCHNG_SIZECHANGED";
}
}
else if ( pChild->IsSet ( PROPERTY_MEMBER ) )
{
// On the object
szMemberDesc = szClass;
szMemberDesc += ", ";
szMemberDesc += pChild->GetTagValue ( PROPERTY_MEMBER );
}
if ( pChild -> IsSet ( PROPERTY_ACCESSIBILITYSTATE) )
{
// we should only allow this on properties that can be set,
if ( ! ( pChild->IsSet ( PROPERTY_SET ) ) )
{
ReportError ( "Accessibility State can only be applied to r/w properties\n" );
return FALSE;
}
if ( szdwFlags [ 0 ] )
{
szdwFlags += "|";
}
szdwFlags += "ELEMCHNG_ACCESSIBILITY";
}
if ( pChild -> IsSet ( PROPERTY_UPDATECOLLECTION ) )
{
if ( szdwFlags [ 0 ] )
{
szdwFlags += "|";
}
szdwFlags += "ELEMCHNG_UPDATECOLLECTION";
}
if ( pChild -> IsSet ( PROPERTY_CLEARCACHES ) )
{
if ( szdwFlags [ 0 ] )
{
szdwFlags += "|";
}
szdwFlags += "ELEMCHNG_CLEARCACHES";
}
if ( pChild -> IsSet ( PROPERTY_STYLEPROP ) )
{
if ( szPropParamDesc [ 0 ] )
szPropParamDesc += " | ";
szPropParamDesc += "PROPPARAM_STYLESHEET_PROPERTY";
}
if ( pChild -> IsSet ( PROPERTY_DONTUSENOTASSIGN ) )
{
if ( szPropParamDesc [ 0 ] )
szPropParamDesc += " | ";
szPropParamDesc += "PROPPARAM_DONTUSENOTASSIGNED";
}
if ( pChild -> IsSet ( PROPERTY_RESIZE ) )
{
if ( szdwFlags [ 0 ] )
{
szdwFlags += "|";
}
szdwFlags += "ELEMCHNG_SIZECHANGED";
}
if ( pChild -> IsSet ( PROPERTY_REMEASURE ) )
{
if ( szdwFlags [ 0 ] )
{
szdwFlags += "|";
}
szdwFlags += "ELEMCHNG_REMEASURECONTENTS";
}
if ( pChild -> IsSet ( PROPERTY_REMEASUREALL ) )
{
if ( szdwFlags [ 0 ] )
{
szdwFlags += "|";
}
szdwFlags += "ELEMCHNG_REMEASUREALLCONTENTS";
}
if ( pChild -> IsSet ( PROPERTY_SITEREDRAW ) )
{
if ( szdwFlags [ 0 ] )
{
szdwFlags += "|";
}
szdwFlags += "ELEMCHNG_SITEREDRAW";
}
char szPropertyDesc [ MAX_LINE_LEN+1 ] ;
pChild -> GetTagValueOrDefault ( szNotPresentDefault, PROPERTY_NOTPRESENTDEFAULT, "0" );
if ( pChild->IsSet( PROPERTY_NOTPRESENTDEFAULT ) && szHandler == "String")
{
szNotPresentDefault = szPreText + szNotPresentDefault;
szNotPresentDefault += szPostText;
}
else if ( szHandler == "Color" && szNotPresentDefault == "0" )
{
// This is a nasty little hack to make for colors
szNotPresentDefault = "-1";
}
// If there's a not assigned default, use it, else use the not present default
pChild -> GetTagValueOrDefault ( szNotAssignedDefault, PROPERTY_NOTSETDEFAULT,
(LPCSTR)szNotPresentDefault );
if ( pChild->IsSet( PROPERTY_NOTSETDEFAULT ) && szHandler == "String")
{
szNotAssignedDefault = szPreText + szNotAssignedDefault;
szNotAssignedDefault += szPostText;
}
else if ( szHandler == "Color" && szNotAssignedDefault == "0" )
{
szNotAssignedDefault = "-1";
}
// szAttribute spevcifies the html name of the property, if not specified the
// property name itself is used.
if ( pChild -> IsSet ( PROPERTY_SZATTRIBUTE ) )
{
szHTMLName = pChild -> GetTagValue ( PROPERTY_SZATTRIBUTE );
sprintf ( (LPSTR) szExposedName,
"_T(\"%s\")",
pChild->GetTagValue ( PROPERTY_NAME ) );
}
else
{
szHTMLName = pChild -> GetTagValue ( PROPERTY_NAME );
strcpy(szExposedName, "NULL");
}
// If the propdesc has a member specified generate a full propdesc
// By setting abstract: AND member: the propdesc can be used for validation
// ( e.g. UnitMeasurement sub-object )
if ( pChild->IsSet ( PROPERTY_ABSTRACT ) && !pChild->IsSet ( PROPERTY_MEMBER ) )
{
// Generate a minimal propdesc, this is how IDispatchEx traverses
// attributes and properties.
sprintf ( (LPSTR) szPropertyDesc,
" s_propdesc%s%s = \n{\n NULL, _T(\"%s\"), %s, (ULONG_PTR)%s, (ULONG_PTR)%s,\n {",
(LPCSTR)szClass,
(LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ),
(LPCSTR)szHTMLName,
(LPCSTR)szExposedName,
(LPCSTR)szNotPresentDefault,
(LPCSTR)szNotAssignedDefault);
}
else
{
// If you're gonna set up a handler, better be a valid one
if ( szHandler == "" )
{
sprintf ( szErrorText, "Invalid Type:%s in Class:%s Property:%s\n",
(LPCSTR)pChild->GetTagValue ( PROPERTY_TYPE ),
(LPCSTR)pClassToken->GetTagValue(CLASS_NAME),
(LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ) );
ReportError ( szErrorText );
return FALSE;
}
char szTempBuf[MAX_LINE_LEN+1];
sprintf ( (LPSTR) szTempBuf, " s_propdesc%s%s =\n{\n#ifdef WIN16\n (PFN_HANDLEPROPERTY)&PROPERTYDESC::handle%sproperty, _T(\"%s\"), %s, (ULONG_PTR)%s, (ULONG_PTR)%s,\n#else\n",
(LPCSTR)szClass,
(LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ),
(LPCSTR)szHandler,
(LPCSTR)szHTMLName,
(LPCSTR)szExposedName,
(LPCSTR)szNotPresentDefault,
(LPCSTR)szNotAssignedDefault);
sprintf ( (LPSTR) szPropertyDesc, "%s PROPERTYDESC::Handle%sProperty, _T(\"%s\"), %s, (ULONG_PTR)%s,(ULONG_PTR)%s,\n#endif\n {", szTempBuf,
(LPCSTR)szHandler,
(LPCSTR)szHTMLName,
(LPCSTR)szExposedName,
(LPCSTR)szNotPresentDefault,
(LPCSTR)szNotAssignedDefault);
}
if ( !ComputePROPDESC_STRUCT ( fpHDLFile, pClassToken, pChild, szHandler, szFnPrefix) )
return FALSE; // Bad error reported...leave
if ( !szdwFlags [ 0 ] )
szdwFlags = "0";
fNumericHandler = FALSE;
if ( !pChild->IsSet ( PROPERTY_ABSTRACT ) && szHandler == "Num" || szHandler == "Enum" || szHandler == "UnitValue" )
{
// Numeric Handlers
fNumericHandler = TRUE;
fprintf ( fpHDLFile, "%s\n {", szPropertyDesc );
if ( szHandler == "Enum" )
{
szPropParamDesc += " | PROPPARAM_ENUM";
}
else if ( pChild -> IsSet ( PROPERTY_ENUMREF ) )
{
// A number with one or more enums
szPropParamDesc += " | PROPPARAM_ENUM | PROPPARAM_ANUMBER";
}
pChild -> GetTagValueOrDefault ( szDispid, PROPERTY_DISPID, "0" );
if ((strcmp(pChild->GetTagValue(PROPERTY_ATYPE), "BSTR") == 0 || strcmp(pChild->GetTagValue(PROPERTY_ATYPE), "VARIANT") == 0) &&
((pChild->IsSet(PROPERTY_CAA) || pChild->IsSet(PROPERTY_SET)) && !pChild->IsSet(PROPERTY_INTERNAL)) ||
(!pChild->IsSet(PROPERTY_CAA) && !pChild->IsSet(PROPERTY_SET) && !pChild->IsSet(PROPERTY_GET)))
{
if (!pChild->IsSet(PROPERTY_MAXSTRLEN))
{
char szErrorText [ MAX_LINE_LEN+1 ];
// Dispid not specified this is an error all methods should be accessible
// from automation.
sprintf ( szErrorText, "maxstrlen required for property: %s::%s in %s.\n",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ),
_pszPDLFileName );
ReportError ( szErrorText );
return FALSE;
}
}
else if (pChild->IsSet(PROPERTY_MAXSTRLEN))
{
char szErrorText [ MAX_LINE_LEN+1 ];
// Dispid not specified this is an error all methods should be accessible
// from automation.
sprintf ( szErrorText, "maxstrlen NOT required for property: %s::%s in %s.\n",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ),
_pszPDLFileName );
ReportError ( szErrorText );
return FALSE;
}
fprintf ( fpHDLFile, "\n %s, %s, %s, %s, %s \n },",
(LPCSTR)szPropParamDesc,
(LPCSTR)szDispid,
(LPCSTR)szdwFlags,
(LPCSTR)&chCustomInvokeIdx[0],
pChild->IsSet(PROPERTY_MAXSTRLEN) ? (LPCSTR)pChild->GetTagValue(PROPERTY_MAXSTRLEN) : "0");
if (fpMaxLenFile && pChild->IsSet(PROPERTY_MAXSTRLEN))
{
fprintf ( fpMaxLenFile, "%s::%s %s\n",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ),
(LPCSTR)pChild->GetTagValue(PROPERTY_MAXSTRLEN) );
}
if ( pChild->IsSet ( PROPERTY_ABSTRACT ) )
{
fprintf ( fpHDLFile, "\n 0, 0" );
}
else
{
if ( !pChild->IsSet ( PROPERTY_VT ) )
{
CString szAType;
szAType = pChild->GetTagValue ( PROPERTY_ATYPE );
if ( szAType == "short" || szAType == "VARIANT_BOOL" )
szVTDef = "VT_I2";
else
szVTDef = "VT_I4";
}
else
{
szVTDef = pChild->GetTagValue ( PROPERTY_VT );
}
if ( pChild -> IsSet ( PROPERTY_GETSETMETHODS ) )
{
fprintf ( fpHDLFile, "\n %s, 0",
(LPCSTR)szVTDef );
}
else if ( pChild -> IsSet ( PROPERTY_CAA ) )
{
fprintf ( fpHDLFile, "\n %s, sizeof(DWORD)",
(LPCSTR)szVTDef );
}
else
{
fprintf ( fpHDLFile, "\n %s, SIZE_OF(%s)",
(LPCSTR)szVTDef, (LPCSTR)szMemberDesc );
}
}
// Fill in the min/max values
// If it's an enum, the min value is a ptr to the enum desc structure
if ( szHandler == "Enum" )
{
if ( pChild->IsSet ( PROPERTY_ABSTRACT ) )
{
fprintf ( fpHDLFile, ", 0, 0,\n" );
}
else
{
// Get the enum mask from the enum named by PROPERTY_TYPE
CTokenListWalker WholeList ( pRuntimeList );
Token *pEnumToken = WholeList.GetNext ( TYPE_ENUM, pChild->GetTagValue ( PROPERTY_TYPE ) );
CString szMin;
pChild->GetTagValueOrDefault ( szMin, PROPERTY_MIN, "0" );
if ( pEnumToken == NULL )
{
sprintf ( szErrorText,
"unknown enum type %s\n",pChild->GetTagValue ( PROPERTY_TYPE ) );
ReportError ( szErrorText );
return FALSE;
}
fprintf ( fpHDLFile, ", %s, (LONG_PTR)&s_enumdesc%s,\n",
(LPCSTR)szMin, pChild->GetTagValue ( PROPERTY_TYPE ) );
}
}
else
{
CString szMax;
CString szMin;
pChild->GetTagValueOrDefault ( szMin, PROPERTY_MIN, "LONG_MIN" );
pChild->GetTagValueOrDefault ( szMax, PROPERTY_MAX, "LONG_MAX" );
fprintf ( fpHDLFile, ", %s, %s,\n", (LPCSTR)szMin, (LPCSTR)szMax );
}
}
else
{
fprintf ( fpHDLFile, "%s\n ", szPropertyDesc );
pChild -> GetTagValueOrDefault ( szDispid, PROPERTY_DISPID, "0" );
if ((strcmp(pChild->GetTagValue(PROPERTY_ATYPE), "BSTR") == 0 || strcmp(pChild->GetTagValue(PROPERTY_ATYPE), "VARIANT") == 0) &&
((pChild->IsSet(PROPERTY_CAA) || pChild->IsSet(PROPERTY_SET)) && !pChild->IsSet(PROPERTY_INTERNAL)) ||
(!pChild->IsSet(PROPERTY_CAA) && !pChild->IsSet(PROPERTY_SET) && !pChild->IsSet(PROPERTY_GET)))
{
if (!pChild->IsSet(PROPERTY_MAXSTRLEN))
{
char szErrorText [ MAX_LINE_LEN+1 ];
// Dispid not specified this is an error all methods should be accessible
// from automation.
sprintf ( szErrorText, "maxstrlen required for property: %s::%s in %s.\n",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ),
_pszPDLFileName );
ReportError ( szErrorText );
return FALSE;
}
}
else if (pChild->IsSet(PROPERTY_MAXSTRLEN))
{
char szErrorText [ MAX_LINE_LEN+1 ];
// Dispid not specified this is an error all methods should be accessible
// from automation.
sprintf ( szErrorText, "maxstrlen NOT required for property: %s::%s in %s.\n",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ),
_pszPDLFileName );
ReportError ( szErrorText );
return FALSE;
}
fprintf ( fpHDLFile, " %s, %s, %s, %s, %s \n",
(LPCSTR)szPropParamDesc,
(LPCSTR)szDispid,
(LPCSTR)szdwFlags,
(LPCSTR)&chCustomInvokeIdx[0],
pChild->IsSet(PROPERTY_MAXSTRLEN) ? (LPCSTR)pChild->GetTagValue(PROPERTY_MAXSTRLEN) : "0");
if (fpMaxLenFile && pChild->IsSet(PROPERTY_MAXSTRLEN))
{
fprintf ( fpMaxLenFile, "%s::%s %s\n",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ),
(LPCSTR)pChild->GetTagValue(PROPERTY_MAXSTRLEN) );
}
}
fprintf ( fpHDLFile, " }," );
if (pEventChild && pChild->IsSet(PROPERTY_SCRIPTLET))
{
fprintf(fpHDLFile, "\n (DWORD_PTR)%s", pEventChild->GetTagValue(METHOD_DISPID));
}
else if ( pChild->IsSet ( PROPERTY_GETSETMETHODS ) )
{
fprintf ( fpHDLFile, "\n PROPERTY_METHOD(%s, GET, %s, Get%s, GET%s)," ,
(LPCSTR)szFnPrefix,
(LPCSTR)szClass, (LPCSTR)pChild->GetTagValue ( PROPERTY_GETSETMETHODS ),
(LPCSTR)pChild->GetTagValue ( PROPERTY_GETSETMETHODS ));
fprintf ( fpHDLFile, "\n PROPERTY_METHOD(%s, SET, %s, Set%s, SET%s)" ,
(LPCSTR)szFnPrefix,
(LPCSTR)szClass, (LPCSTR)pChild->GetTagValue ( PROPERTY_GETSETMETHODS ),
(LPCSTR)pChild->GetTagValue ( PROPERTY_GETSETMETHODS ));
}
else if ( pChild->IsSet ( PROPERTY_ABSTRACT ) )
{
}
else if ( szMemberDesc [ 0 ] )
{
fprintf ( fpHDLFile, "\n offsetof(%s)",
(LPCSTR)szMemberDesc );
}
if ( fNumericHandler && pChild->IsSet ( PROPERTY_ENUMREF ) &&
!pChild->IsSet ( PROPERTY_ABSTRACT ) )
{
CTokenListWalker WholeList ( pRuntimeList );
Token *pEnumToken = WholeList.GetNext ( TYPE_ENUM,
pChild->GetTagValue ( PROPERTY_ENUMREF ) );
if ( pEnumToken == NULL )
{
sprintf ( szErrorText,
"unknown enum type %s\n",pChild->GetTagValue ( PROPERTY_ENUMREF ) );
ReportError ( szErrorText );
return FALSE;
}
if ( !szMemberDesc [ 0 ] )
{
fprintf ( fpHDLFile, "\n 0, &s_enumdesc%s",
pChild->GetTagValue ( PROPERTY_ENUMREF ) );
}
else
{
fprintf ( fpHDLFile, "\n &s_enumdesc%s",
pChild->GetTagValue ( PROPERTY_ENUMREF ) );
}
}
fprintf ( fpHDLFile, "\n};\n\n" );
return TRUE;
}
BOOL CPDLParser::BuildMethodSignature(Token *pChild,
CString &szTypesSig,
CString &szArgsType,
BOOL &fBSTRArg,
BOOL &fVARIANTArg,
int &cArgs,
int &cRequiredArgs,
char *pDefaultParams[MAX_ARGS],
char *pDefaultStrParams[MAX_ARGS])
{
Token *pArgToken;
CTokenListWalker ArgListWalker(pChild);
char *pDispatchType;
char szErrorText [ MAX_LINE_LEN+1 ];
cArgs = 0;
cRequiredArgs = 0;
fBSTRArg = FALSE;
fVARIANTArg = FALSE;
// Loop thru all arguments.
while ( (pArgToken = ArgListWalker.GetNext()) != NULL &&
pArgToken -> GetType () == TYPE_METHOD_ARG )
{
fBSTRArg |= (strcmp(pArgToken->GetTagValue(METHODARG_TYPE), "BSTR") == 0);
fVARIANTArg |= (!pArgToken->IsSet(METHODARG_OUT) && (strcmp(pArgToken->GetTagValue(METHODARG_TYPE), "VARIANT") == 0 || strcmp(pArgToken->GetTagValue(METHODARG_TYPE), "VARIANT*") == 0));
// Looking for a return value.
if ( pArgToken -> IsSet ( METHODARG_RETURNVALUE ) )
{
char *pWS;
szTypesSig = pArgToken -> GetTagValue ( METHODARG_TYPE );
// Remove any underscores in the type name.
while ((pWS = szTypesSig.FindChar('_')))
{
while (*pWS = *(pWS + 1))
pWS++;
*pWS = '\0';
}
// Should this type be mapped to IDispatch?
pDispatchType = MapTypeToIDispatch ( szTypesSig );
if (pDispatchType)
{
szTypesSig = pDispatchType;
}
}
else
{
CString szArg;
char *pWS;
if ( pArgToken->IsSet ( METHODARG_OPTIONAL ) )
{
// little o + zero + little o, prepended to the type signals
// the type is optional.
szArg = "o0o";
}
if ( pArgToken -> IsSet ( METHODARG_DEFAULTVALUE ) )
{
// Signal default.
szArg = "oDo";
if (cArgs >= MAX_ARGS)
{
sprintf ( szErrorText, "PDL parser can only handle upto 8 parameters (increase MAX_ARGS) %s in file %s.\n",
(LPCSTR)pChild->GetTagValue ( METHOD_NAME ),
_pszPDLFileName );
ReportError ( szErrorText );
return FALSE;
}
// Currently I only handle 2 types of default values numbers and
// strings. If any other appear then I'll need to add those as
// well.
if ( strcmp (pArgToken -> GetTagValue ( METHODARG_TYPE ), "BSTR") == 0)
{
if (pDefaultStrParams)
pDefaultStrParams[cArgs] = pArgToken -> GetTagValue ( METHODARG_DEFAULTVALUE );
}
else if (pDefaultParams)
{
pDefaultParams[cArgs] = pArgToken -> GetTagValue ( METHODARG_DEFAULTVALUE );
}
}
else
{
// If not optional and not defaultValue then the argument is
// required and no defaults could have appeared in between.
if ( !pArgToken->IsSet ( METHODARG_OPTIONAL ) )
{
// Insure that once a default argument is hit all arguments from
// that point to the last argument im the function are either
// defaultValue or optional.
if (cRequiredArgs != cArgs)
{
sprintf ( szErrorText, "Default arguments must be contiguous to last argument %s in file %s.\n",
(LPCSTR)pChild->GetTagValue ( METHOD_NAME ),
_pszPDLFileName );
ReportError ( szErrorText );
return FALSE;
}
// Arguments without a defaultValue/optional are required args.
// Unless the argument is a safe array than any number of
// arguments can be specified 0 to n arguments
if (strcmp((LPCSTR)(pArgToken -> GetTagValue(METHODARG_TYPE)), "SAFEARRAY(VARIANT)") != 0)
// Not a safearray so it's a required argument.
cRequiredArgs++;
}
}
szArg += pArgToken -> GetTagValue ( METHODARG_TYPE );
if (szArg == "oDoVARIANT")
{
sprintf ( szErrorText, "Default arguments cannot be VARIANT %s in file %s.\n",
(LPCSTR)pChild->GetTagValue ( METHOD_NAME ),
_pszPDLFileName );
ReportError ( szErrorText );
return FALSE;
}
if ( pArgToken->IsSet ( METHODARG_OPTIONAL ) &&
!(szArg == "o0oVARIANT" || szArg == "o0oVARIANT*") )
{
sprintf ( szErrorText, "Optional arguments can ONLY be VARIANT or VARIANT* %s in file %s.\n",
(LPCSTR)pChild->GetTagValue ( METHOD_NAME ),
_pszPDLFileName );
ReportError ( szErrorText );
return FALSE;
}
// Should this type be mapped to IDispatch?
pDispatchType = MapTypeToIDispatch ( szArg );
if (pDispatchType)
{
// Remap to IDispatch* or IDispatch**
szArg = pDispatchType;
}
cArgs++;
// Remove any underscores in the type name.
while ((pWS = szArg.FindChar('_')))
{
while (*pWS = *(pWS + 1))
pWS++;
*pWS = '\0';
}
szArgsType += "_";
szArgsType += (LPCSTR)szArg;
}
}
return TRUE;
}
BOOL CPDLParser::ComputeMethod ( Token *pClassToken, Token *pChild )
{
CString szTypesSig;
CString szArgsType;
CString szDispid;
CTokenListWalker ArgListWalker ( pChild );
char chCustomInvokeIdx[128];
int cArgs = 0;
int cRequiredArgs = 0;
char szErrorText [ MAX_LINE_LEN+1 ];
char *pDefaultParams[MAX_ARGS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
char *pDefaultStrParams[MAX_ARGS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
BOOL fBSTRArg;
BOOL fVARIANTArg;
if (!BuildMethodSignature(pChild,
szTypesSig,
szArgsType,
fBSTRArg,
fVARIANTArg,
cArgs,
cRequiredArgs,
pDefaultParams,
pDefaultStrParams))
return FALSE;
// Any default values?
if (cArgs != cRequiredArgs)
{
int i;
// Spit out any default string constants.
for ( i = cRequiredArgs; i < cArgs; i++)
{
if ( pDefaultStrParams[i] )
{
fprintf ( fpHDLFile, "const TCHAR s_strDef%s%s%i[] = _T(%s);\n",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChild->GetTagValue ( METHOD_NAME ),
i - cRequiredArgs,
pDefaultStrParams[i] );
}
}
fprintf ( fpHDLFile, "const DEFAULTARGDESC s_defArg%s%s =\n{\n",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChild->GetTagValue ( METHOD_NAME ) );
// Spit out the all of all default constants
for ( i = cRequiredArgs; i < cArgs; i++)
{
if ( pDefaultStrParams[i] )
{
fprintf ( fpHDLFile, " (DWORD_PTR)s_strDef%s%s%i,\n",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChild->GetTagValue ( METHOD_NAME ),
i - cRequiredArgs );
}
else
{
fprintf ( fpHDLFile, " (DWORD_PTR)%s,\n", pDefaultParams[i] ? pDefaultParams[i] : "\"\"" );
}
}
fprintf ( fpHDLFile, "};\n" );
}
// If no return value then set the retVal to void.
if (!szTypesSig[0])
{
szTypesSig = "void";
}
// If no arguments then set the argList to void.
if (!szArgsType[0])
{
szArgsType = "_void";
}
szTypesSig += szArgsType;
szDispid = pChild->GetTagValue(METHOD_DISPID);
if (szDispid[0])
{
// Write out the function signature for this method
// only do this if a dispid exists. Methods without dispid
// are not accessible through automation.
if ( !FindAndAddSignature ( "Method", szTypesSig, &chCustomInvokeIdx[0] ) )
return FALSE;
}
fprintf ( fpHDLFile, "EXTERN_C const PROPERTYDESC_METHOD s_methdesc%s%s = \n{\n",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChild->GetTagValue ( METHOD_NAME ));
fprintf ( fpHDLFile, " NULL, NULL, _T(\"%s\"), (ULONG)0, (ULONG)0,\n {\n",
(LPCSTR)pChild->GetTagValue ( METHOD_NAME ));
if (!szDispid[0])
{
// Dispid not specified this is an error all methods should be accessible
// from automation.
sprintf ( szErrorText, "DISPID required for method: %s::%s in %s.\n",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChild->GetTagValue ( METHOD_NAME ),
_pszPDLFileName );
ReportError ( szErrorText );
return FALSE;
}
if (fBSTRArg || fVARIANTArg)
{
if (!pChild->IsSet(METHOD_MAXSTRLEN))
{
// Dispid not specified this is an error all methods should be accessible
// from automation.
sprintf ( szErrorText, "maxstrlen required for method: %s::%s in %s.\n",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChild->GetTagValue ( METHOD_NAME ),
_pszPDLFileName );
ReportError ( szErrorText );
return FALSE;
}
}
else if (pChild->IsSet(METHOD_MAXSTRLEN))
{
// Dispid not specified this is an error all methods should be accessible
// from automation.
sprintf ( szErrorText, "maxstrlen NOT required for method: %s::%s in %s.\n",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChild->GetTagValue ( METHOD_NAME ),
_pszPDLFileName );
ReportError ( szErrorText );
return FALSE;
}
fprintf ( fpHDLFile, " %s, %s, 0, %s, %s\n },\n ",
pChild->IsSet(METHOD_RESTRICTED) ? "PROPPARAM_RESTRICTED" : "0",
(LPCSTR)szDispid,
(LPCSTR)&chCustomInvokeIdx[0],
pChild->IsSet(METHOD_MAXSTRLEN) ? (LPCSTR)pChild->GetTagValue(METHOD_MAXSTRLEN) : "0");
if (fpMaxLenFile && pChild->IsSet(METHOD_MAXSTRLEN))
{
fprintf ( fpMaxLenFile, "%s::%s %s\n",
(LPCSTR)pClassToken->GetTagValue(CLASS_NAME),
(LPCSTR)pChild->GetTagValue(METHOD_NAME),
(LPCSTR)pChild->GetTagValue(METHOD_MAXSTRLEN) );
}
if ( cArgs != cRequiredArgs )
{
fprintf ( fpHDLFile, "&s_defArg%s%s, ",
(LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pChild->GetTagValue ( METHOD_NAME ) );
}
else
{
fprintf ( fpHDLFile, "NULL, " );
}
fprintf ( fpHDLFile, "%i, %i\n};\n\n",
cArgs,
cRequiredArgs );
return TRUE;
}
BOOL CPDLParser::GeneratePROPDESCs ( void )
{
Token *pClassToken;
Token *pChild;
// Only generate def's for this file
CTokenListWalker TokenList ( pRuntimeList, _pszPDLFileName );
// Generate propdescs for every property token in every class ( in this file )
while ( pClassToken = TokenList.GetNext( TYPE_CLASS ) )
{
fprintf ( fpHDLFile, "\n" );
CTokenListWalker ChildList ( pClassToken );
// if ( pClassToken -> IsSet ( CLASS_ABSTRACT ) )
// {
// fprintf ( fpHDLFile, "\n#ifndef _PROPDESCS_EXTERNAL\n" );
// }
fprintf ( fpHDLFile, "\n#define _%s_PROPDESCS_\n", pClassToken -> GetTagValue ( CLASS_NAME ) );
// Walk the super class propdescs looking for properties
while ( pChild = ChildList.GetNext() )
{
if ( pChild->nType == TYPE_PROPERTY &&
_stricmp(pChild->GetTagValue(PROPERTY_NOPROPDESC), "nameonly") != 0 )
{
if ( !ComputeProperty ( pClassToken, pChild ) )
return FALSE;
}
else if ( pChild->nType == TYPE_METHOD && !pChild->IsSet(METHOD_NOPROPDESC))
{
if (!ComputeMethod(pClassToken, pChild) )
return FALSE;
}
else
{
continue;
}
}
if (fpMaxLenFile)
fprintf(fpMaxLenFile, "\n");
}
return TRUE;
}
void CPDLParser::GenerateThunkContext ( Token *pClassToken )
{
CTokenListWalker ChildList (pClassToken);
Token *pChildToken;
while (pChildToken = ChildList.GetNext())
{
if( (pChildToken->GetType() == TYPE_METHOD && pChildToken->IsSet(METHOD_THUNKCONTEXT)) ||
(pChildToken->GetType() == TYPE_PROPERTY && pChildToken->IsSet(PROPERTY_THUNKCONTEXT)) )
{
GenerateSingleThunkContextPrototype(pClassToken, pChildToken, FALSE);
}
if( (pChildToken->GetType() == TYPE_METHOD && pChildToken->IsSet(METHOD_THUNKNODECONTEXT)) ||
(pChildToken->GetType() == TYPE_PROPERTY && pChildToken->IsSet(PROPERTY_THUNKNODECONTEXT)) )
{
GenerateSingleThunkContextPrototype(pClassToken, pChildToken, TRUE);
}
}
}
void CPDLParser::GenerateSingleThunkContextPrototype ( Token *pClassToken, Token * pChildToken, BOOL fNodeContext )
{
CString szProp;
Token *pArgToken;
if (pChildToken->GetType() == TYPE_METHOD)
{
CTokenListWalker ArgListWalker(pChildToken);
BOOL fFirst = TRUE;
fprintf(fpHDLFile, " STDMETHODIMP %s(", (LPCSTR)pChildToken->GetTagValue(METHOD_NAME));
while (pArgToken = ArgListWalker.GetNext())
{
if (!fFirst)
fprintf(fpHDLFile, ",");
fprintf(fpHDLFile, "%s %s",
ConvertType((LPCSTR)pArgToken->GetTagValue ( METHODARG_TYPE )),
(LPCSTR)pArgToken -> GetTagValue ( METHODARG_ARGNAME ) );
fFirst = FALSE;
}
if(fNodeContext)
{
fprintf(fpHDLFile, "%sCTreeNode *pNode);\n", fFirst?"":",");
}
else
{
fprintf(fpHDLFile, "%sTEAROFF_THUNK*ptt);\n", fFirst?"":",");
}
}
else
{
if (pChildToken->IsSet(PROPERTY_SET))
{
fprintf(fpHDLFile, " STDMETHODIMP set_%s(%s v, %s);\n",
(LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME),
(LPCSTR)pChildToken -> GetTagValue(PROPERTY_ATYPE),
fNodeContext?"CTreeNode *pNode":"TEAROFF_THUNK *ptt");
}
if (pChildToken->IsSet(PROPERTY_GET))
{
fprintf(fpHDLFile, " STDMETHODIMP get_%s(%s *p, %s);\n",
(LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME),
(LPCSTR)pChildToken -> GetTagValue(PROPERTY_ATYPE),
fNodeContext?"CTreeNode *pNode":"TEAROFF_THUNK *ptt");
}
}
}
void CPDLParser::GenerateThunkContextImplemenation ( Token *pClassToken )
{
CTokenListWalker ChildList (pClassToken);
Token *pChildToken;
while (pChildToken = ChildList.GetNext())
{
if( (pChildToken->GetType() == TYPE_METHOD && pChildToken->IsSet(METHOD_THUNKCONTEXT)) ||
(pChildToken->GetType() == TYPE_PROPERTY && pChildToken->IsSet(PROPERTY_THUNKCONTEXT)) )
{
GenerateSingleThunkContextImplementation(pClassToken, pChildToken, FALSE);
}
if( (pChildToken->GetType() == TYPE_METHOD && pChildToken->IsSet(METHOD_THUNKNODECONTEXT)) ||
(pChildToken->GetType() == TYPE_PROPERTY && pChildToken->IsSet(PROPERTY_THUNKNODECONTEXT)) )
{
GenerateSingleThunkContextImplementation(pClassToken, pChildToken, TRUE);
}
}
}
void CPDLParser::GenerateSingleThunkContextImplementation ( Token *pClassToken, Token * pChildToken, BOOL fNodeContext )
{
CString szProp;
Token *pArgToken;
fprintf(fpHDLFile, "#ifdef USE_STACK_SPEW\n#pragma check_stack(off)\n#endif\n");
if (pChildToken->GetType() == TYPE_METHOD)
{
CTokenListWalker ArgListWalker(pChildToken);
BOOL fFirst = TRUE;
fprintf(fpHDLFile, "STDMETHODIMP %s::ContextThunk_%s(",
(LPCSTR)pClassToken->GetTagValue(CLASS_NAME),
(LPCSTR)pChildToken->GetTagValue(METHOD_NAME));
while (pArgToken = ArgListWalker.GetNext())
{
if (!fFirst)
fprintf(fpHDLFile, ",");
fprintf(fpHDLFile, "%s %s",
ConvertType((LPCSTR)pArgToken->GetTagValue ( METHODARG_TYPE )),
(LPCSTR)pArgToken -> GetTagValue ( METHODARG_ARGNAME ) );
fFirst = FALSE;
}
if(fNodeContext)
{
fprintf(fpHDLFile, ")\n"
"{\n"
" CTreeNode* pNode;\n"
" CONTEXTTHUNK_SETTREENODE\n"
" return %s(", (LPCSTR)pChildToken->GetTagValue(METHOD_NAME));
}
else
{
fprintf(fpHDLFile, ")\n"
"{\n"
" TEAROFF_THUNK* ptt;\n"
" CONTEXTTHUNK_SETTEAROFFTHUNK\n"
" return %s(", (LPCSTR)pChildToken->GetTagValue(METHOD_NAME));
}
fFirst = TRUE;
ArgListWalker.Reset();
while (pArgToken = ArgListWalker.GetNext())
{
if (!fFirst)
fprintf(fpHDLFile, ",");
fprintf(fpHDLFile, "%s",
(LPCSTR)pArgToken -> GetTagValue(METHODARG_ARGNAME));
fFirst = FALSE;
}
fprintf(fpHDLFile, "%s%s);\n}\n", fFirst?"":",", fNodeContext?"pNode":"ptt");
}
else
{
if (pChildToken->IsSet(PROPERTY_SET))
{
fprintf(fpHDLFile,
"STDMETHODIMP %s::ContextThunk_set_%s(%s v)\n"
"{\n%s return set_%s(v,%s);\n}\n",
(LPCSTR)pClassToken->GetTagValue(CLASS_NAME),
(LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME),
(LPCSTR)pChildToken->GetTagValue(PROPERTY_ATYPE),
fNodeContext
? " CTreeNode* pNode;\n"
" CONTEXTTHUNK_SETTREENODE\n"
: " TEAROFF_THUNK* ptt;\n"
" CONTEXTTHUNK_SETCONTEXTTHUNK\n",
(LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME),
fNodeContext ? "pNode" : "ptt");
}
if (pChildToken->IsSet(PROPERTY_GET))
{
fprintf(fpHDLFile,
"STDMETHODIMP %s::ContextThunk_get_%s(%s *p)\n"
"{\n%s return get_%s(p,%s);\n}\n",
(LPCSTR)pClassToken->GetTagValue(CLASS_NAME),
(LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME),
(LPCSTR)pChildToken->GetTagValue(PROPERTY_ATYPE),
fNodeContext
? " CTreeNode* pNode;\n"
" CONTEXTTHUNK_SETTREENODE\n"
: " TEAROFF_THUNK* ptt;\n"
" CONTEXTTHUNK_SETCONTEXTTHUNK\n",
(LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME),
fNodeContext ? "pNode" : "ptt");
}
}
fprintf(fpHDLFile, "#ifdef USE_STACK_SPEW\n#pragma check_stack(on)\n#endif\n");
}
BOOL CPDLParser::GenerateHDLFile ( void )
{
Token *pClassToken;
BOOL bHashTableExists;
int numVTblPropDescs;
CTokenListWalker ThisFilesList ( pRuntimeList, _pszPDLFileName );
fprintf ( fpHDLFile, "\n" );
fprintf ( fpHDLFile, "// %s.hdl\n", _pszOutputFileRoot );
fprintf ( fpHDLFile, "\n" );
fprintf ( fpHDLFile, "#ifdef _hxx_\n" );
fprintf ( fpHDLFile, "\n" );
fprintf ( fpHDLFile, "#include \"%s.h\"\n", _pszOutputFileRoot );
fprintf ( fpHDLFile, "\n" );
// Generate the DISPID's, one for each member of each class
fprintf ( fpLOGFile, "Generating DISPID's...\n" );
GenerateClassDISPIDs();
GenerateInterfaceDISPIDs();
GenerateEventDISPIDs( fpHDLFile, TRUE );
fprintf ( fpHDLFile, "\n" );
fprintf ( fpHDLFile, "#endif _hxx_\n" );
fprintf ( fpHDLFile, "\n" );
fprintf ( fpHDLFile, "#undef _hxx_\n" );
fprintf ( fpHDLFile, "\n" );
fprintf ( fpHDLFile, "#ifdef _cxx_\n" );
fprintf ( fpHDLFile, "\n" );
// Generate the enum definitions
fprintf ( fpLOGFile, "Generating CPP Enum Defs...\n" );
GenerateCPPEnumDefs();
// Generate the property descriptors
fprintf ( fpLOGFile, "Generating PROPDESC's...\n" );
if ( !GeneratePROPDESCs() )
goto Error;
#ifdef COMPLUS_SHIM
// ***TLL*** COM+: Not spitting COM+ proxies for internal.pdl and mshtmext.pdl need to do, shouldn't special case.
if ((_stricmp(_pszPDLFileName, "internal.pdl") != 0) && (_stricmp(_pszPDLFileName, "mshtmext.pdl") != 0))
{
GenComPlusESI(); // Output any local interfaces for COM+
}
#endif // COMPLUS_SHIM
// For each TYPE_CLASS in this file generate a propdesc array and vtable
// array for the class.
while ( pClassToken = ThisFilesList.GetNext( TYPE_CLASS ) )
{
// Generate propdescs for every property token in every class ( in this file )
fprintf ( fpLOGFile, "Generating PROPDESC Arrays...\n" );
if ( !GenerateCPC( pClassToken ) )
goto Error;
// Generate the vtable array for classes in this file
fprintf ( fpLOGFile, "Generating VTable Arrays...\n" );
GenerateVTableArray(pClassToken, &bHashTableExists);
// Generate the propdesc array in vtable order for classes in this file
fprintf ( fpLOGFile, "Generating propdesc Arrays in vtbl order...\n" );
GeneratePropDescsInVtblOrder(pClassToken, &numVTblPropDescs);
// Abstract classes don't have propdesc arrays or vtable arrays.
if ( !pClassToken -> IsSet ( CLASS_ABSTRACT ) )
{
fprintf ( fpHDLFile, "\nconst HDLDESC %s::s_apHdlDescs = { ",
pClassToken -> GetTagValue ( CLASS_NAME ) );
// Store the Mondo DISPID int he HDLDesc so we can find it for GetTypeInfo
if ( HasMondoDispInterface ( pClassToken ) )
{
CString szDispName;
// Map to mondo dispinterface as default dispatch interface.
szDispName = (pClassToken->IsSet(CLASS_COCLASSNAME)) ?
pClassToken->GetTagValue (CLASS_COCLASSNAME) :
pClassToken->GetTagValue(CLASS_NAME);
fprintf ( fpHDLFile, " &DIID_Disp%s,", (LPCSTR)szDispName );
}
else
{
fprintf ( fpHDLFile, " NULL," );
}
if ( bHashTableExists )
{
fprintf ( fpHDLFile, "&%s::s_StringTableAggregate, ",
pClassToken -> GetTagValue ( CLASS_NAME ) );
}
else
{
fprintf ( fpHDLFile, "NULL, ");
}
if ( numVTblPropDescs )
{
fprintf ( fpHDLFile, "%s::s_ppropdescsInVtblOrder%s};\n",
pClassToken->GetTagValue(CLASS_NAME), pClassToken->GetTagValue(CLASS_INTERFACE) );
}
else
{
fprintf ( fpHDLFile, "NULL};\n" );
}
}
}
fprintf ( fpLOGFile, "Generating Property Methods...\n" );
if ( !GeneratePropMethodImplementation() )
goto Error;
fprintf ( fpLOGFile, "Generating Cascaded Property Method Implementations...\n" );
fprintf ( fpHDLFile, "// Cascaded Property get method implementations\n\n" );
ThisFilesList.Reset();
while ( pClassToken = ThisFilesList.GetNext( TYPE_CLASS ) )
{
GenerateGetAAXImplementations(pClassToken);
GenerateThunkContextImplemenation(pClassToken);
}
fprintf ( fpHDLFile, "\n" );
fprintf ( fpHDLFile, "#endif _cxx_\n" );
fprintf ( fpHDLFile, "\n" );
fprintf ( fpHDLFile, "#undef _cxx_\n" );
fprintf ( fpHDLFile, "\n" );
fprintf ( fpLOGFile, "Generating Class Includes...\n" );
if ( !GenerateClassIncludes() )
goto Error;
return TRUE;
Error:
return FALSE;
}
FILE *OpenMaxlengthFile(LPCSTR pszPDLFileName, LPCSTR pszOutputPath)
{
char chMaxLenFileName[255];
FILE *fpMaxLenFile = NULL;
BOOL fOpenNew = TRUE;
strcpy(chMaxLenFileName, pszOutputPath);
strcat(chMaxLenFileName, FILENAME_SEPARATOR_STR "maxlen.txt");
fpMaxLenFile = fopen(chMaxLenFileName, "r");
if (fpMaxLenFile)
{
char chMarker[6];
if (fread(chMarker, sizeof(char), 5, fpMaxLenFile))
{
if (!_stricmp(chMarker, "XXXXX"))
{
fOpenNew = FALSE;
}
}
fclose(fpMaxLenFile);
}
if (fOpenNew)
{
fpMaxLenFile = fopen(chMaxLenFileName, "w");
if (fpMaxLenFile)
{
fprintf(fpMaxLenFile, "XXXXX Key Value Glossary:\n");
fprintf(fpMaxLenFile, "-------------------------------\n");
fprintf(fpMaxLenFile, "pdlUrlLen = 4096 // url strings\n");
fprintf(fpMaxLenFile, "pdlToken = 128 // strings that really are some form of a token\n");
fprintf(fpMaxLenFile, "pdlLength = 128 // strings that really are numeric lengths\n");
fprintf(fpMaxLenFile, "pdlColor = 128 // strings that really are color values\n");
fprintf(fpMaxLenFile, "pdlNoLimit = 0xFFFF // strings that have no limit on their max lengths\n");
fprintf(fpMaxLenFile, "pdlEvent = pdlNoLimit // strings that could be assigned to onfoo event properties\n\n");
fprintf(fpMaxLenFile, "MAX LENGTH CONSTANTS FOR OM PROPERTIES AND METHODS\n");
fprintf(fpMaxLenFile, "-----------------------------------------------------------------------------------\n\n");
}
}
else
{
fpMaxLenFile = fopen(chMaxLenFileName, "a");
}
return fpMaxLenFile;
}
int
CPDLParser::Parse ( char *szInputFile,
char *szOutputFileRoot,
char *szPDLFileName,
char *szOutputPath,
BOOL fDebugging )
{
#if 0
if (strcmp(szPDLFileName, "iframe.pdl") == 0)
__asm {int 3};
#endif
int nReturnCode = 0;
char szFileName [ MAX_PATH+1 ];
char szErrorText [ MAX_LINE_LEN+1 ];
#ifdef COMPLUS_SHIM
BOOL fWriteHeader = FALSE;
#endif
_pszPDLFileName = szPDLFileName;
_pszOutputFileRoot = szOutputFileRoot;
_pszInputFile = szInputFile;
_pszOutputPath = szOutputPath;
fpMaxLenFile = OpenMaxlengthFile(szPDLFileName, szOutputPath);
// Read the input file a line at a time, for each line tokenise and
// parse
strcpy ( szFileName, szOutputPath );
strcat ( szFileName, "LOG" );
fpLOGFile = fopen ( szFileName, "w" );
if ( !fpLOGFile )
{
printf ( szErrorText, "Can't open log file %s\n", szFileName );
ReportError ( szErrorText );
goto error;
}
fprintf ( fpLOGFile, "InputBuffer = %s\n", szInputFile );
fprintf ( fpLOGFile, "OuputFileRoot = %s\n", szOutputFileRoot );
fprintf ( fpLOGFile, "PDLFileName = %s\n", szPDLFileName );
fprintf ( fpLOGFile, "LogFileName =% s\n", szFileName );
// All files open and raring to go....
if ( !ParseInputFile ( fDebugging ) )
{
goto error;
}
// Create the HDL File
strcpy ( szFileName, szOutputFileRoot );
strcat ( szFileName, ".hdl" );
fpHDLFile = fopen ( szFileName, "w" );
if ( !fpHDLFile )
{
printf ( szErrorText, "Can't open HDL output file %s\n", szFileName );
ReportError ( szErrorText );
goto error;
}
#ifdef COMPLUS_SHIM
// Create the COM+ header file
strcpy ( szFileName, _pszOutputPath );
strcat ( szFileName, "\\" );
strcat ( szFileName, "MSProxy.h" );
fpHComPlusFile = fopen ( szFileName, "r" );
if (!fpHComPlusFile)
{
fWriteHeader = TRUE;
}
else
{
fclose(fpHComPlusFile);
}
fpHComPlusFile = fopen ( szFileName, "a" );
if ( !fpHComPlusFile )
{
printf ( szErrorText, "Can't open COM+ output file %s\n", szFileName );
ReportError ( szErrorText );
goto error;
}
// Only write the header first time through not when each PDL is parsed.
if (fWriteHeader)
{
fprintf(fpHComPlusFile, "[managed, com] __interface ICOMCookie\n");
fprintf(fpHComPlusFile, "{\n");
fprintf(fpHComPlusFile, "public:\n");
fprintf(fpHComPlusFile, "\tunsigned int getCOMCookie();\n");
fprintf(fpHComPlusFile, "};\n\n");
}
// Create the COM+ source file
strcpy ( szFileName, _pszOutputPath );
strcat ( szFileName, "\\" );
strcat ( szFileName, "MSProxy.cpp" );
fpCComPlusFile = fopen ( szFileName, "r" );
if (!fpCComPlusFile)
{
fWriteHeader = TRUE;
}
else
{
fclose(fpCComPlusFile);
}
fpCComPlusFile = fopen ( szFileName, "a" );
if ( !fpCComPlusFile )
{
printf ( szErrorText, "Can't open COM+ output file %s\n", szFileName );
ReportError ( szErrorText );
goto error;
}
// Only write the header first time through not when each PDL is parsed.
if (fWriteHeader)
{
fprintf(fpCComPlusFile, "#import <MSCorLib.dll>\n\n");
fprintf(fpCComPlusFile, "// Some types COM+ doesn't know remapped.\n");
fprintf(fpCComPlusFile, "#define LONG long\n\n");
fprintf(fpCComPlusFile, "#include \"MSProxy.h\"\n");
fprintf(fpCComPlusFile, "#include \"TComPlus.hxx\"\n\n\n");
}
#endif // COMPLUS_SHIM
// Create the IDL File
strcpy ( szFileName, szOutputFileRoot );
strcat ( szFileName, ".idl" );
fpIDLFile = fopen ( szFileName, "w" );
if ( !fpIDLFile )
{
printf ( szErrorText, "Can't open IDL output file %s\n", szFileName );
ReportError ( szErrorText );
goto error;
}
// Create the external Header file for the SDK users
// Create the HDL File
strcpy ( szFileName, szOutputFileRoot );
strcat ( szFileName, ".h" ); // For now
fpHeaderFile = fopen ( szFileName, "w" );
if ( !fpHeaderFile )
{
printf ( szErrorText, "Can't open Header output file %s\n", szFileName );
ReportError ( szErrorText );
goto error;
}
// Create the external DISPIDs file for the SDK users
strcpy ( szFileName, szOutputFileRoot );
strcat ( szFileName, ".dsp" ); // For now
fpDISPIDFile = fopen ( szFileName, "w" );
if ( !fpDISPIDFile )
{
printf ( szErrorText, "Can't open DISPID output file %s\n", szFileName );
ReportError ( szErrorText );
goto error;
}
// Create function signatures required for the custom OLEAutomation invoke.
if ( !LoadSignatures (szOutputPath) )
{
ReportError ( "Signature file missing" );
goto error;
}
#if COLLECT_STATISTICS==1
LoadStatistics (szOutputPath);
#endif
// Parsed Successfully - generate HDL file
if ( !GenerateHDLFile () )
{
printf ( szErrorText, "Can't create HDL output file %s%s.hdl\n",
szOutputFileRoot, szFileName );
ReportError ( szErrorText );
goto error;
}
strcpy ( szFileName, szOutputFileRoot );
strcat ( szFileName, ".idl" ); // For now hxx
if ( !GenerateIDLFile( szFileName ) )
{
printf ( szErrorText, "Can't create IDL file %s\n", szFileName );
ReportError ( szErrorText );
goto error;
}
// Generate the .H file with just enums & interface decls in
GenerateHeaderFile();
// Generate the external DISPID's file
GenerateExternalInterfaceDISPIDs();
GenerateEventDISPIDs ( fpDISPIDFile, FALSE );
// Create/Open the HTML index file
strcpy ( szFileName, szOutputPath );
strcat ( szFileName, FILENAME_SEPARATOR_STR "AllIndex.htm" );
fpHTMIndexFile = fopen ( szFileName, "a+" );
/* rgardner - commented out for now - not very up-to-date or useful any more
// Create the HTM File
strcpy ( szFileName, szOutputFileRoot );
strcat ( szFileName, ".htm" );
fpHTMFile = fopen ( szFileName, "w" );
if ( !GenerateHTMFile( ) )
{
printf ( szErrorText, "Can't create HTM file %s\n", szFileName );
ReportError ( szErrorText );
goto error;
}
*/
// Update the signature file is any changes.
if (!SaveSignatures( szOutputPath ))
{
ReportError ( "Signature file save problem." );
goto error;
}
#if COLLECT_STATISTICS==1
SaveStatistics (szOutputPath);
#endif
goto cleanup;
error:
if ( nReturnCode == 0 )
nReturnCode = 1;
cleanup:
return nReturnCode;
}
#if COLLECT_STATISTICS==1
void CPDLParser::LoadStatistics ( char *pszOutputPath )
{
BOOL bRetVal;
char *buffer = NULL;
CString szFileName;
FILE *fpStatFile = NULL;
szFileName = pszOutputPath;
szFileName += FILENAME_SEPARATOR_STR "stats.dat";
fpStatFile = fopen ( szFileName, "r" );
if ( !fpStatFile )
{
char chInitFuncSig[2] = { '\0', '\0' };
fpStatFile = fopen ( szFileName, "w+");
if ( !fpStatFile )
{
ReportError ( "Can't create statistics file" );
goto error;
}
fwrite ( chInitFuncSig, 1, sizeof(chInitFuncSig), fpStatFile );
}
if ( fseek( fpStatFile, 0, SEEK_END ) == 0 )
{
fpos_t pos;
if ( fgetpos( fpStatFile, &pos ) == 0 )
{
int i = 0;
int cLines;
buffer = new char[pos];
if (buffer == NULL)
goto error;
fseek( fpStatFile, 0, SEEK_SET );
if ( fread ( buffer, 1, pos, fpStatFile ) != pos )
goto error;
// Intialize to 0.
for (i = 0; i < MAX_STATS; i++)
rgcStats[i] = 0;
// Populate the statics array.
i = 0;
cLines = 0;
while ( buffer[i] || buffer[i + 1] )
{
int cStr = strlen(buffer + i);
rgcStats[cLines] = atol(buffer + i);
cLines ++;
i += cStr + 1;
}
}
}
bRetVal = TRUE;
cleanup:
delete buffer;
fclose ( fpStatFile );
return;
error:
bRetVal = FALSE;
goto cleanup;
}
void CPDLParser::SaveStatistics ( char *pszOutputPath )
{
//DebugBreak();
BOOL bRetVal = TRUE;
if (rgcStats)
{
int i;
CString szFileName;
FILE *fpStatFile = NULL;
char buffer[32];
szFileName = pszOutputPath;
szFileName += FILENAME_SEPARATOR_STR "stats.dat";
fpStatFile = fopen ( szFileName, "w" );
// Write array to file.
if ( fseek( fpStatFile, 0, SEEK_SET ) != 0 )
return;
i = 0;
while (i < MAX_STATS)
{
sprintf( buffer, "%i", rgcStats[i] );
fwrite ( buffer, 1, strlen(buffer) + 1, fpStatFile );
i++;
}
// Double NULL at the end.
buffer[0] = '\0';
buffer[1] = '\0';
fwrite ( &buffer, 1, 2, fpStatFile );
fclose(fpStatFile);
}
return;
}
#endif
void CPDLParser::RemoveSignatures()
{
if (rgszSignatures)
{
int i = cSignatures;
while (i--)
delete [] rgszSignatures[i];
delete [] rgszSignatures;
rgszSignatures = NULL;
}
if (rgszIIDs)
{
int i = cIIDs;
while (i--)
delete [] rgszIIDs[i];
delete [] rgszIIDs;
rgszIIDs = NULL;
}
}
BOOL CPDLParser::LoadSignatures ( char *pszOutputPath )
{
BOOL bRetVal;
char *buffer = NULL;
CString szFileName;
FILE *fpSigFile = NULL;
rgszSignatures = NULL;
cOnFileSignatures = 0;
cOnFileIIDs = 0;
cSignatures = 0;
cIIDs = 0;
szFileName = pszOutputPath;
szFileName += FILENAME_SEPARATOR_STR "funcsig.dat";
/*
if (strcmp(_pszPDLFileName, "select.pdl") == 0 || strcmp(_pszPDLFileName, "header.pdl") == 0)
__asm { int 3 };
*/
fpSigFile = fopen ( szFileName, "rb" );
if ( !fpSigFile )
{
char chInitFuncSig[6] = { '\0', '\0', '\0', '\0', '\0', '\0' };
fpSigFile = fopen ( szFileName, "w+");
if ( !fpSigFile )
{
ReportError ( "Can't create function signature file" );
goto error;
}
fwrite ( chInitFuncSig, 1, sizeof(chInitFuncSig), fpSigFile );
}
if ( fseek( fpSigFile, 0, SEEK_END ) == 0 )
{
fpos_t pos;
if ( fgetpos( fpSigFile, &pos ) == 0 )
{
int i = 0;
int cLines;
buffer = new char[pos];
if (buffer == NULL)
goto error;
fseek( fpSigFile, 0, SEEK_SET );
fread ( buffer, 1, pos, fpSigFile );
// Number of entries for each signatures and IIDs
cOnFileSignatures = buffer[0] & 0x000000ff; // First byte is # signature
cOnFileIIDs = buffer[1] & 0x000000ff; // 2nd byte is # IIDs
// Pre-allocate the signature array.
rgszSignatures = new char *[cOnFileSignatures + 1];
if ( !rgszSignatures )
goto error;
// Pre-allocate the IIDs array.
rgszIIDs = new char *[cOnFileIIDs + 1];
if ( !rgszIIDs )
goto error;
// Intialize to NULL for error handling.
for (i = 0; i <= cOnFileSignatures; i++)
rgszSignatures[i] = NULL;
cSignatures = cOnFileSignatures;
for (i = 0; i <= cOnFileIIDs; i++)
rgszIIDs[i] = NULL;
cIIDs = cOnFileIIDs;
// Populate the signature array.
i = 4;
cLines = 0;
while ( cLines != cSignatures )
{
int cStr = strlen(buffer + i);
rgszSignatures[cLines] = new char[cStr + 1];
if (!rgszSignatures[cLines])
goto error;
strcpy(rgszSignatures[cLines], buffer + i);
cLines ++;
i += cStr + 1;
}
// Populate the IIDs array.
cLines = 0;
while ( cLines != cIIDs )
{
int cStr = strlen(buffer + i);
rgszIIDs[cLines] = new char[cStr + 1];
if (!rgszIIDs[cLines])
goto error;
strcpy(rgszIIDs[cLines], buffer + i);
cLines ++;
i += cStr + 1;
}
}
}
bRetVal = TRUE;
cleanup:
fclose ( fpSigFile );
return bRetVal;
error:
delete [] buffer;
RemoveSignatures();
bRetVal = FALSE;
goto cleanup;
}
BOOL CPDLParser::SaveSignatures ( char *pszOutputPath )
{
if (rgszSignatures || rgszIIDs)
{
if (cOnFileSignatures != cSignatures || cOnFileIIDs != cIIDs)
{
int i;
CString szFileName;
FILE *fpSigFile = NULL;
char cHeaderFuncSig[4] = { '\0', '\0', '\0', '\0' };
szFileName = pszOutputPath;
szFileName += FILENAME_SEPARATOR_STR "funcsig.dat";
fpSigFile = fopen ( szFileName, "wb" );
// Write array to file.
if ( fseek( fpSigFile, 0, SEEK_SET ) != 0 )
return FALSE;
// Write out the header on count of each type.
cHeaderFuncSig[0] = (char)cSignatures;
cHeaderFuncSig[1] = (char)cIIDs;
fwrite ( cHeaderFuncSig, 1, sizeof(cHeaderFuncSig), fpSigFile );
i = 0;
while (i < cSignatures)
{
if ( rgszSignatures[i] )
{
fwrite ( rgszSignatures[i], 1, strlen(rgszSignatures[i]) + 1, fpSigFile );
}
i++;
}
i = 0;
while (i < cIIDs)
{
if ( rgszIIDs[i] )
{
fwrite ( rgszIIDs[i], 1, strlen(rgszIIDs[i]) + 1, fpSigFile );
}
i++;
}
// Write out extra zero to mark end of file.
cHeaderFuncSig[0] = '\0';
fwrite ( cHeaderFuncSig, 1, 1, fpSigFile );
fclose(fpSigFile);
}
// Dispose of signature array (IIDs is disposed of too).
RemoveSignatures();
}
return TRUE;
}
void
CPDLParser::MakeSignature (LPCSTR szType, LPCSTR szSignature, CString & szLookup)
{
char *szWork;
// Any empty string for type or signature is an error.
if (!szType[0] || !szSignature[0])
{
return;
}
// Replace all * with p (e.g., BSTR * is BSTRP and long * is longP).
while ((szWork = strchr(szSignature, '*')) != NULL)
*szWork = 'p';
// Replace all ( with P.
while ((szWork = strchr(szSignature, '(')) != NULL)
*szWork = 'P';
// Replace all ) with P.
while ((szWork = strchr(szSignature, ')')) != NULL)
*szWork = 'P';
szLookup = szType;
szLookup += "_";
szLookup += szSignature;
}
BOOL CPDLParser::FindAndAddSignature ( LPCSTR szType, LPCSTR szSignature, LPSTR pszInvokeMethod )
{
BOOL bRetVal = NULL;
CString szLookup;
char **rgNewArray = NULL;
if (pszInvokeMethod && rgszSignatures)
{
strcpy( pszInvokeMethod, "ERROR in PDLParse: No custom invoke method");
MakeSignature(szType, szSignature, szLookup);
// Look for the signature
for (int i = 0; i < cSignatures; i++)
{
if ( strcmp ( rgszSignatures[i], szLookup ) == 0 )
{
goto success;
}
}
// If not found then add this signature.
cSignatures++;
rgNewArray = new char *[cSignatures + 1]; // Take into account the NULL at end.
if (!rgNewArray)
goto cleanup;
memcpy(rgNewArray, rgszSignatures, sizeof(char *) * cSignatures);
rgNewArray[cSignatures - 1] = new char[szLookup.Length() + 1];
strcpy(rgNewArray[cSignatures - 1], szLookup);
rgNewArray[cSignatures] = NULL;
delete rgszSignatures;
rgszSignatures = rgNewArray;
success:
strcpy(pszInvokeMethod, "IDX_");
strcat(pszInvokeMethod, (LPCSTR)szLookup);
bRetVal = TRUE;
}
cleanup:
return bRetVal;
}
int CPDLParser::FindAndAddIIDs ( CString szInterface )
{
char **rgNewArray = NULL;
// Any empty string interface name is an error.
if (szInterface.Length() == 0)
return -1; // Error.
// Look for the signature
for (int i = 0; i < cIIDs; i++)
{
if ( strcmp ( rgszIIDs[i], (LPCSTR)szInterface ) == 0 )
{
goto success;
}
}
// If not found then add this IID.
cIIDs++;
rgNewArray = new char *[cIIDs + 1]; // Take into account the NULL at end.
if (!rgNewArray)
return -1;
memcpy(rgNewArray, rgszIIDs, sizeof(char *) * cIIDs);
rgNewArray[cIIDs - 1] = new char[szInterface.Length() + 1];
strcpy(rgNewArray[cIIDs - 1], (LPCSTR)szInterface);
rgNewArray[cIIDs] = NULL;
delete rgszIIDs;
rgszIIDs = rgNewArray;
success:
return i;
}
BOOL CPDLParser::GenerateIDLFile ( char *szFileName )
{
CTokenListWalker ThisFileList ( pRuntimeList, _pszPDLFileName );
Token * pInterfaceToken;
Token * pClassToken;
Token * pEnumToken;
Token * pStructToken;
ThisFileList.Reset();
while ( pInterfaceToken = ThisFileList.GetNext ( TYPE_EVENT ) )
{
if ( !pInterfaceToken -> IsSet ( EVENT_ABSTRACT ) &&
pInterfaceToken -> IsSet ( EVENT_GUID ) )
{
GenerateIDLInterfaceDecl ( pInterfaceToken,
pInterfaceToken -> GetTagValue ( EVENT_GUID ),
pInterfaceToken -> GetTagValue ( EVENT_SUPER ) );
}
}
ThisFileList.Reset();
while (pEnumToken = ThisFileList.GetNext(TYPE_ENUM))
{
GenerateIncludeEnum(pEnumToken, FALSE, fpIDLFile);
}
//
// Generate all the structs
//
ThisFileList.Reset();
while (pStructToken = ThisFileList.GetNext(TYPE_STRUCT))
{
GenerateStruct(pStructToken, fpIDLFile);
}
ThisFileList.Reset();
while ( pInterfaceToken = ThisFileList.GetNext ( TYPE_INTERFACE ) )
{
if ( !pInterfaceToken -> IsSet ( INTERFACE_ABSTRACT ) &&
pInterfaceToken -> IsSet ( INTERFACE_GUID ) )
{
GenerateIDLInterfaceDecl ( pInterfaceToken,
pInterfaceToken -> GetTagValue ( INTERFACE_GUID ),
pInterfaceToken -> GetTagValue ( INTERFACE_SUPER ) );
}
else if ( !pInterfaceToken -> IsSet ( INTERFACE_ABSTRACT ) &&
!pInterfaceToken -> IsSet ( INTERFACE_GUID ) )
{
// Generate a forward declare
CString szInterfaceName;
szInterfaceName = pInterfaceToken -> GetTagValue ( INTERFACE_NAME );
if ( szInterfaceName != "IDispatch" &&
szInterfaceName != "IUnknown" )
{
fprintf ( fpIDLFile, "interface %s;\n",
pInterfaceToken -> GetTagValue ( NAME_TAG ) );
}
}
}
ThisFileList.Reset();
while (pClassToken = ThisFileList.GetNext(TYPE_CLASS))
{
CTokenListWalker ChildWalker(pClassToken);
Token *pChildToken;
int cImplements = 0;
// Find out how many implements are in the class.
while (pChildToken = ChildWalker.GetNext())
{
if (pChildToken->GetType() == TYPE_IMPLEMENTS)
{
cImplements++;
}
}
// Any class with more than one implements needs a mondodispid to be specified.
if (pClassToken->IsSet(CLASS_GUID) && cImplements && !pClassToken->IsSet(CLASS_MONDOGUID))
{
char szErrorText [ MAX_LINE_LEN+1 ];
sprintf(szErrorText,
"class: %s needs a mondoguid when implements are specified for a coclass.\n",
pClassToken->GetTagValue(CLASS_NAME));
ReportError(szErrorText);
return FALSE;
}
// Generate non-dual dispinterface? This is determined by the mondoguid
// keyword being used int the class. If this guid is specified then
// we'll generate the mondodisp interface is use it as the default
// dispatch interface for the coclass.
if (pClassToken->IsSet(CLASS_MONDOGUID))
{
LPSTR pMondoGUID;
CString szInterface;
szInterface = pClassToken->GetTagValue(CLASS_INTERFACE);
pInterfaceToken = FindInterface(szInterface);
pMondoGUID = pClassToken->GetTagValue(CLASS_MONDOGUID);
// If we have a GUID then the dispinterface GUID must be in the
// range 0x3050f500 to 0x3050f5a0
if (pMondoGUID[0] != '3' ||
pMondoGUID[1] != '0' ||
pMondoGUID[2] != '5' ||
pMondoGUID[3] != '0' ||
pMondoGUID[4] != 'f' ||
pMondoGUID[5] != '5' ||
!((pMondoGUID[6] >= '0' &&
pMondoGUID[6] <= '9') ||
pMondoGUID[6] == 'a') ||
!((pMondoGUID[7] >= '0' &&
pMondoGUID[7] <= '9') ||
(pMondoGUID[7] >= 'a' &&
pMondoGUID[7] <= 'f')))
{
char szErrorText [ MAX_LINE_LEN+1 ];
sprintf(szErrorText,
"The mondoguid must be in the range 0x3050f500 to 0x3050f5a0 for class: %s\n",
pClassToken->GetTagValue(CLASS_NAME));
ReportError(szErrorText);
return FALSE;
}
// Generate the default dispinterface
GenerateIDLInterfaceDecl(pInterfaceToken,
pMondoGUID,
pInterfaceToken->GetTagValue(INTERFACE_SUPER),
TRUE,
pClassToken);
}
if ( pClassToken-> IsSet(CLASS_GUID) &&
pClassToken->IsSet(CLASS_INTERFACE))
{
GenerateCoClassDecl(pClassToken);
}
}
return TRUE;
}
void CPDLParser::GenerateIDLInterfaceDecl (Token *pInterfaceToken,
char *pszGUID,
char *pszSuper,
BOOL fDispInterface/*= FALSE*/,
Token *pClassToken/*= NULL*/)
{
BOOL fImplements = FALSE;
if ( pInterfaceToken -> GetType() == TYPE_EVENT )
{
fprintf ( fpIDLFile, "[\n hidden,\n" );
fprintf ( fpIDLFile, " uuid(%s)\n]\ndispinterface %s\n{",
pszGUID, pInterfaceToken -> GetTagValue ( NAME_TAG ) );
fprintf ( fpIDLFile, "\nproperties:\nmethods:\n" );
}
else
{
if (fDispInterface)
{
fprintf ( fpIDLFile, "[\n hidden,\n" );
fprintf ( fpIDLFile, " uuid(%s)\n]\ndispinterface Disp%s\n{\nproperties:\nmethods:\n",
pszGUID,
pClassToken->IsSet(CLASS_COCLASSNAME) ?
pClassToken->GetTagValue(CLASS_COCLASSNAME) :
pClassToken->GetTagValue(CLASS_NAME));
}
else
{
if (!PrimaryTearoff(pInterfaceToken) && (!pszSuper || !*pszSuper))
ReportError ( "Interfaces w/o tearoff need super:IDispatch\n" );
if (pInterfaceToken->IsSet(INTERFACE_CUSTOM) &&
pszSuper &&
*pszSuper)
{
fprintf(fpIDLFile, "[\n object,\n pointer_default(unique),\n" );
fprintf ( fpIDLFile, " uuid(%s)\n]\ninterface %s : %s\n{\n",
pszGUID,
pInterfaceToken -> GetTagValue ( NAME_TAG ),
pszSuper);
}
else
{
fprintf ( fpIDLFile, "[\n odl,\n oleautomation,\n dual,\n" );
fprintf ( fpIDLFile, " uuid(%s)\n]\ninterface %s : %s\n{\n",
pszGUID,
pInterfaceToken -> GetTagValue ( NAME_TAG ),
(PrimaryTearoff(pInterfaceToken) && _stricmp(pszSuper, "IHTMLDocument")) ? "IDispatch" : pszSuper);
}
}
}
// Any implements in the class if so then we want the order of the mongo dispinterface to be decided
// by the order of the implements and not the super chain.
if (fDispInterface)
{
CTokenListWalker ChildWalker(pClassToken);
Token *pChildToken;
while (pChildToken = ChildWalker.GetNext())
{
fImplements = pChildToken->GetType() == TYPE_IMPLEMENTS;
if (fImplements)
break;
}
}
// Use the super chain for mongo dispinterface?
if (!fImplements)
// Yes.
GenerateMkTypelibDecl(pInterfaceToken, fDispInterface, pClassToken);
// Any other interfaces exposed in the coclass which are not part of the
// primary interface chain? Look for implements keyword.
if (fDispInterface)
{
CTokenListWalker ChildWalker(pClassToken);
Token *pChildToken;
CString szInterface;
Token *pInterfToken;
while (pChildToken = ChildWalker.GetNext())
{
if (pChildToken->GetType() == TYPE_IMPLEMENTS)
{
szInterface = pChildToken->GetTagValue(IMPLEMENTS_NAME);
pInterfToken = FindInterface(szInterface);
if (pInterfToken)
{
GenerateMkTypelibDecl(pInterfToken, fDispInterface, pClassToken);
}
}
}
}
fprintf(fpIDLFile, "};\n");
}
void CPDLParser::ComputePropType ( Token *pPropertyToken,
CString &szProp, BOOL fComment )
{
char szText [ MAX_LINE_LEN+1 ];
szProp = "";
// Through the index/indextype & index1/indextype1 pdl tags
// you can provide up to two additional args for the property definition
sprintf ( szText, fComment ? "/* [in] */ %s %s" : "[in] %s %s",
pPropertyToken -> GetTagValue ( PROPERTY_INDEXTYPE ),
pPropertyToken -> GetTagValue ( PROPERTY_INDEX ) );
pPropertyToken -> AddParam ( szProp, PROPERTY_INDEX, szText );
sprintf ( szText, fComment ? "/* [in] */ %s %s" : "[in] %s %s",
pPropertyToken -> GetTagValue ( PROPERTY_INDEXTYPE1 ),
pPropertyToken -> GetTagValue ( PROPERTY_INDEX1 ));
pPropertyToken -> AddParam ( szProp, PROPERTY_INDEX1, szText );
if ( szProp [ 0 ] != '\0' )
szProp += ",";
}
void CPDLParser::GenerateMkTypelibDecl ( Token *pInterfaceToken, BOOL fDispInterface/* = FALSE*/, Token *pClass /* =NULL */)
{
Token *pChildToken;
Token *pArgToken;
CString szArg;
CString szProp;
CString szAutomationType;
BOOL fFirst;
CString szInterfaceName,szMethodName,szPropertyName;
CTokenListWalker ChildWalker ( pInterfaceToken );
if ( pInterfaceToken -> GetType() == TYPE_EVENT &&
pInterfaceToken -> IsSet ( EVENT_SUPER ) )
{
CTokenListWalker WholeList(pRuntimeList);
Token *pSuperEvent = WholeList.GetNext ( TYPE_EVENT,
pInterfaceToken -> GetTagValue ( EVENT_SUPER ) );
if ( pSuperEvent )
GenerateMkTypelibDecl ( pSuperEvent );
}
// Special non-dual dispinterface for the default when the primary interface
// is a tearoff.
if (fDispInterface)
{
Token *pSuperIntf;
CString szInterface;
szInterface = pInterfaceToken->GetTagValue(INTERFACE_SUPER);
pSuperIntf = FindInterface(szInterface);
if (pSuperIntf)
GenerateMkTypelibDecl(pSuperIntf, fDispInterface, pClass);
}
szInterfaceName = pInterfaceToken->GetTagValue ( INTERFACE_NAME );
szInterfaceName.ToUpper();
while ( pChildToken = ChildWalker.GetNext() )
{
if ( pChildToken -> GetType() == TYPE_METHOD )
{
// if nopropdesc is set, then this method doesn't
// participate in the typelib/mondo interface. this happens
// when the method exists in a base class/interface as well.
if ( pChildToken->IsSet(METHOD_NOPROPDESC) && fDispInterface)
continue;
// Does the property name exist in another interface then the primary
// interface had better have the override. Otherwise, it's an error
// MIDL will not allow overloading names.
if (fDispInterface && pClass)
{
CString szPrimaryInterface;
Token *pPriInterf;
Token *pExclusiveMember;
szPrimaryInterface = pClass->GetTagValue(CLASS_INTERFACE);
pPriInterf = FindInterface(szPrimaryInterface);
// If working on non-primary interface make sure the method isn't overloaded on
// the primary, if so it better be marked exclusive.
if (_strcmpi(szInterfaceName, szPrimaryInterface))
{
pExclusiveMember = FindMethodInInterfaceWOPropDesc(pPriInterf, pChildToken, TRUE);
if (pExclusiveMember)
{
char szErrorText [ MAX_LINE_LEN+1 ];
if (pExclusiveMember->IsSet(METHOD_EXCLUSIVETOSCRIPT))
continue;
// Overloaded method -- illegal.
sprintf(szErrorText, "method %s:%s is overloaded - illegal.\n",
(LPCSTR)pClass->GetTagValue(CLASS_NAME),
(LPCSTR)pExclusiveMember->GetTagValue(METHOD_NAME));
ReportError(szErrorText);
return;
}
}
}
if ( pChildToken -> IsSet ( METHOD_VARARG) )
{
fprintf ( fpIDLFile, " [vararg");
}
else
{
fprintf ( fpIDLFile, " [");
}
szMethodName = pChildToken -> GetTagValue ( METHOD_NAME );
if (pChildToken->IsSet(METHOD_NOPROPDESC))
{
if (pChildToken->IsSet(METHOD_SZINTERFACEEXPOSE))
szMethodName = pChildToken->GetTagValue(METHOD_SZINTERFACEEXPOSE);
}
szMethodName.ToUpper();
if ( pChildToken -> IsSet ( METHOD_DISPID ) )
{
fprintf ( fpIDLFile, "%sid(DISPID_%s_%s)",
pChildToken -> IsSet ( METHOD_VARARG ) ? "," : "",
(LPCSTR)szInterfaceName, (LPCSTR)szMethodName );
}
CTokenListWalker ArgListWalker ( pChildToken );
if (pChildToken->IsSet(METHOD_NOPROPDESC) &&
pChildToken->IsSet(METHOD_SZINTERFACEEXPOSE))
{
szMethodName = pChildToken->GetTagValue(METHOD_SZINTERFACEEXPOSE);
}
else
{
szMethodName = pChildToken->GetTagValue(METHOD_NAME);
}
if (fDispInterface)
{
szAutomationType = "void";
while ( pArgToken = ArgListWalker.GetNext() )
{
if (pArgToken->IsSet(METHODARG_RETURNVALUE))
{
szAutomationType = pArgToken->IsSet(METHODARG_ATYPE ) ?
pArgToken->GetTagValue(METHODARG_ATYPE) :
pArgToken->GetTagValue(METHODARG_TYPE);
}
// If the last character is a pointer then the pointer
// should be removed because that is for dual C++ style
// interface. DispInterface doesn't need the retval
// specified as a parameter hence the need for
// HRESULT funcName(BOOL*) instead of BOOL funcName ().
int iSzLength = szAutomationType.Length();
if (iSzLength && szAutomationType[iSzLength - 1] == '*')
{
char szTypeNoPtr[MAX_LINE_LEN+1];
strncpy(szTypeNoPtr, szAutomationType, iSzLength - 1);
szTypeNoPtr[iSzLength - 1] = '\0';
szAutomationType = szTypeNoPtr;
}
}
fprintf ( fpIDLFile, "] %s %s(",
(LPCSTR)szAutomationType,
(LPCSTR)szMethodName );
ArgListWalker.Reset();
}
else
{
fprintf ( fpIDLFile, "] %s %s(",
pChildToken -> GetTagValue ( METHOD_RETURNTYPE ),
(LPCSTR)szMethodName );
}
fFirst = TRUE;
while ( pArgToken = ArgListWalker.GetNext() )
{
if (!(fDispInterface && pArgToken->IsSet(METHODARG_RETURNVALUE)))
{
szArg = "";
if ( !fFirst )
fprintf ( fpIDLFile, "," );
#ifndef WIN16_PARSER
pArgToken -> AddParamStr ( szArg, METHODARG_DEFAULTVALUE, "defaultvalue(%s)" );
#endif
pArgToken -> AddParam ( szArg, METHODARG_OPTIONAL, "optional" );
pArgToken -> AddParam ( szArg, METHODARG_RETURNVALUE, "retval" );
pArgToken -> AddParam ( szArg, METHODARG_IN, "in" );
pArgToken -> AddParam ( szArg, METHODARG_OUT, "out" );
fprintf ( fpIDLFile, "[%s] %s %s",
(LPCSTR)szArg,
// Fixing a bug in the old code
// Should really get the atype - allow the type if atype not set
pArgToken -> IsSet ( METHODARG_ATYPE ) ?
pArgToken -> GetTagValue ( METHODARG_ATYPE ) :
pArgToken -> GetTagValue ( METHODARG_TYPE ),
pArgToken -> GetTagValue ( METHODARG_ARGNAME ) );
fFirst = FALSE;
}
}
fprintf ( fpIDLFile, ");\n" );
}
else // Property
{
ComputePropType ( pChildToken, szProp, FALSE );
szAutomationType = pChildToken -> GetTagValue ( PROPERTY_ATYPE );
// if nopropdesc is set, then this property doesn't
// participate in the typelib/mondo interface. this happens
// when the property exists in a base class/interface as well.
if (pChildToken->IsSet(PROPERTY_NOPROPDESC) && fDispInterface)
continue;
// Does the property name exist in another interface then the primary
// interface had better have the override. Otherwise, it's an error
// MIDL will not allow overloading names.
if (fDispInterface && pClass)
{
CString szPrimaryInterface;
Token *pPriInterf;
Token *pExclusiveMember;
szPrimaryInterface = pClass->GetTagValue(CLASS_INTERFACE);
pPriInterf = FindInterface(szPrimaryInterface);
// If working on non-primary interface make sure the property isn't overloaded on
// the primary, if so it better be marked exclusive.
if (_strcmpi(szInterfaceName, szPrimaryInterface))
{
pExclusiveMember = FindMethodInInterfaceWOPropDesc(pPriInterf, pChildToken, TRUE);
if (pExclusiveMember)
{
char szErrorText [ MAX_LINE_LEN+1 ];
if (pExclusiveMember->IsSet(PROPERTY_EXCLUSIVETOSCRIPT))
continue;
// Overloaded method -- illegal.
sprintf(szErrorText, "property %s:%s is overloaded - illegal.\n",
(LPCSTR)pClass->GetTagValue(CLASS_NAME),
(LPCSTR)pExclusiveMember->GetTagValue(PROPERTY_NAME));
ReportError(szErrorText);
return;
}
}
}
if ( pChildToken -> IsSet ( PROPERTY_SET ) )
{
#if COLLECT_STATISTICS==1
// Collect statistics on total number of property sets.
CollectStatistic(NUM_SETPROPERTY, GetStatistic(NUM_SETPROPERTY) + 1);
if (FindEnum ( pChildToken ))
CollectStatistic(NUM_SETENUMS, GetStatistic(NUM_SETENUMS) + 1);
#endif
// If it's an object valued property, generate a propputref,
// otherwise generate a propput
//
if ( pChildToken -> IsSet ( PROPERTY_OBJECT ) )
{
szArg = " [propputref";
}
else
{
szArg = " [propput";
}
if ( pChildToken -> IsSet ( PROPERTY_DISPID ) )
{
szArg += ", id(DISPID_";
szPropertyName = pChildToken->GetTagValue(PROPERTY_NAME);
if (pChildToken->IsSet(PROPERTY_NOPROPDESC))
{
if (pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE))
szPropertyName = pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE);
}
szPropertyName.ToUpper();
szArg += (LPCSTR)szInterfaceName;
szArg += "_";
szArg += (LPCSTR)szPropertyName;
szArg += ")";
}
pChildToken -> AddParam ( szArg, PROPERTY_DISPLAYBIND, "displaybind" );
pChildToken -> AddParam ( szArg, PROPERTY_BINDABLE, "bindable" );
pChildToken -> AddParam ( szArg, PROPERTY_HIDDEN, "hidden" );
pChildToken -> AddParam ( szArg, PROPERTY_RESTRICTED, "restricted" );
#ifndef WIN16_PARSER
pChildToken -> AddParam ( szArg, PROPERTY_NONBROWSABLE, "nonbrowsable" );
#endif
pChildToken -> AddParam ( szArg, PROPERTY_SOURCE, "source" );
if (pChildToken->IsSet(PROPERTY_NOPROPDESC) &&
pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE))
{
szPropertyName = pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE);
}
else
{
szPropertyName = pChildToken->GetTagValue(PROPERTY_NAME);
}
if (fDispInterface)
{
fprintf ( fpIDLFile, "%s] void %s(%s%s v);\n",
(LPCSTR)szArg, (LPCSTR)szPropertyName,
(LPCSTR)szProp, (LPCSTR)szAutomationType );
}
else
{
fprintf ( fpIDLFile, "%s] HRESULT %s(%s[in] %s v);\n",
(LPCSTR)szArg, (LPCSTR)szPropertyName,
(LPCSTR)szProp, (LPCSTR)szAutomationType );
}
}
if ( pChildToken -> IsSet ( PROPERTY_GET ) )
{
#if COLLECT_STATISTICS==1
// Collect statistics on total number of property sets.
CollectStatistic(NUM_GETPROPERTY, GetStatistic(NUM_GETPROPERTY) + 1);
if (FindEnum ( pChildToken ))
CollectStatistic(NUM_GETENUMS, GetStatistic(NUM_GETENUMS) + 1);
#endif
szArg = " [propget";
szArg += ", id(DISPID_";
szPropertyName = pChildToken->GetTagValue(PROPERTY_NAME);
if (pChildToken->IsSet(PROPERTY_NOPROPDESC))
{
if (pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE))
szPropertyName = pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE);
}
szPropertyName.ToUpper();
szArg += (LPCSTR)szInterfaceName;
szArg += "_";
szArg += (LPCSTR)szPropertyName;
szArg += ")";
pChildToken -> AddParam ( szArg, PROPERTY_DISPLAYBIND, "displaybind" );
pChildToken -> AddParam ( szArg, PROPERTY_BINDABLE, "bindable" );
pChildToken -> AddParam ( szArg, PROPERTY_HIDDEN, "hidden" );
pChildToken -> AddParam ( szArg, PROPERTY_RESTRICTED, "restricted" );
#ifndef WIN16_PARSER
pChildToken -> AddParam ( szArg, PROPERTY_NONBROWSABLE, "nonbrowsable" );
#endif
pChildToken -> AddParam ( szArg, PROPERTY_SOURCE, "source" );
if (pChildToken->IsSet(PROPERTY_NOPROPDESC) &&
pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE))
{
szPropertyName = pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE);
}
else
{
szPropertyName = pChildToken->GetTagValue(PROPERTY_NAME);
}
if (fDispInterface)
{
fprintf ( fpIDLFile, "%s] %s %s();\n",
(LPCSTR)szArg,
(LPCSTR)szAutomationType,
(LPCSTR)szPropertyName);
}
else
{
fprintf ( fpIDLFile, "%s] HRESULT %s(%s[retval, out] %s * p);\n",
(LPCSTR)szArg, (LPCSTR)szPropertyName,
(LPCSTR)szProp, (LPCSTR)szAutomationType );
}
}
}
}
}
void CPDLParser::GenerateMidlInterfaceDecl ( Token *pInterfaceToken, char *pszGUID,
char *pszSuper )
{
Token *pChildToken;
Token *pArgToken;
CString szArg;
CString szProp;
BOOL fFirst;
if ( pInterfaceToken -> GetType() == TYPE_EVENT )
return;
fprintf ( fpIDLFile, "[\n local,\n object,\n pointer_default(unique),\n" );
fprintf ( fpIDLFile, " uuid(%s)\n]\ninterface %s : %s\n{\n",
pInterfaceToken -> GetTagValue ( INTERFACE_GUID ),
pInterfaceToken -> GetTagValue ( INTERFACE_NAME ),
pInterfaceToken -> GetTagValue ( INTERFACE_SUPER ) );
CTokenListWalker ChildWalker ( pInterfaceToken );
while ( pChildToken = ChildWalker.GetNext() )
{
if ( pChildToken -> GetType() == TYPE_METHOD )
{
fprintf ( fpIDLFile, " %s %s(",
pChildToken -> GetTagValue ( METHOD_RETURNTYPE ),
pChildToken -> GetTagValue ( METHOD_NAME ) );
fFirst = TRUE;
CTokenListWalker ArgListWalker ( pChildToken );
while ( pArgToken = ArgListWalker.GetNext() )
{
szArg = "";
if ( !fFirst )
fprintf ( fpIDLFile, "," );
pArgToken -> AddParam ( szArg, METHODARG_IN, "in" );
pArgToken -> AddParam ( szArg, METHODARG_OUT, "out" );
fprintf ( fpIDLFile, "[%s] %s %s", (LPCSTR)szArg,
// Fixing a bug in the old code
// Should realy get the atype - allow the type if atype not set
pArgToken -> IsSet ( METHODARG_ATYPE ) ?
pArgToken -> GetTagValue ( METHODARG_ATYPE ) :
pArgToken -> GetTagValue ( METHODARG_TYPE ),
pArgToken -> GetTagValue ( METHODARG_ARGNAME ) );
fFirst = FALSE;
}
fprintf ( fpIDLFile, ");\n" );
}
else
{
// Property
ComputePropType ( pChildToken, szProp, FALSE );
if ( pChildToken -> IsSet ( PROPERTY_SET ))
{
fprintf ( fpIDLFile, " HRESULT put_%s(%s [in] %s v);\n",
(LPCSTR)pChildToken -> GetTagValue ( PROPERTY_NAME ),
(LPCSTR)szProp,
pChildToken -> GetTagValue ( PROPERTY_ATYPE) );
}
if ( pChildToken -> IsSet ( PROPERTY_GET ))
{
fprintf ( fpIDLFile,
" HRESULT get_%s(%s[out] %s * p);\n",
pChildToken -> GetTagValue ( PROPERTY_NAME ),
(LPCSTR)szProp,
pChildToken -> GetTagValue ( PROPERTY_ATYPE));
}
}
}
fprintf ( fpIDLFile, "}\n" );
}
BOOL CPDLParser::HasMondoDispInterface ( Token *pClassToken )
{
CTokenListWalker ChildWalker(pClassToken);
Token *pChildToken;
int cImplements = 0;
// Find out how many implements are in the class.
while (pChildToken = ChildWalker.GetNext())
{
if (pChildToken->GetType() == TYPE_IMPLEMENTS)
{
cImplements++;
}
}
// Any class with more than one implements a guid and a mondoguid will have
// a mondo dispinterface.
return (pClassToken->IsSet(CLASS_GUID) && cImplements && pClassToken->IsSet(CLASS_MONDOGUID));
}
void CPDLParser::GenerateCoClassDecl ( Token *pClassToken )
{
CString szName;
CString szDispName;
CString szInterfSuper;
BOOL fHasMondoDispInterface;
BOOL fElement = FALSE;
if (pClassToken->IsSet(CLASS_COCLASSNAME))
szName = pClassToken->GetTagValue(CLASS_COCLASSNAME);
else
szName = pClassToken->GetTagValue(CLASS_NAME);
fprintf(fpIDLFile, "[\n %suuid(%s)\n]\n",
pClassToken->IsSet(CLASS_CONTROL) ? "control,\n " : "",
pClassToken->GetTagValue(CLASS_GUID));
fprintf(fpIDLFile, "coclass %s\n{\n", (LPCSTR)szName );
fHasMondoDispInterface = HasMondoDispInterface(pClassToken);
if (fHasMondoDispInterface)
{
// Map to mondo dispinterface as default dispatch interface.
szDispName = (pClassToken->IsSet(CLASS_COCLASSNAME)) ?
pClassToken->GetTagValue (CLASS_COCLASSNAME) :
pClassToken->GetTagValue(CLASS_NAME);
}
else
{
// Map to the primary interface as default dispatch interface.
szDispName = pClassToken->GetTagValue(CLASS_INTERFACE);
}
fprintf(fpIDLFile, " [default] %sinterface %s%s;\n",
fHasMondoDispInterface ? "disp" : "",
fHasMondoDispInterface ? "Disp" : "",
(LPCSTR)szDispName);
if (pClassToken->IsSet(CLASS_EVENTS))
{
fprintf(fpIDLFile, " [source, default] dispinterface %s;\n",
pClassToken->GetTagValue(CLASS_EVENTS));
}
if (pClassToken->IsSet(CLASS_NONPRIMARYEVENTS1))
{
fprintf(fpIDLFile, " [source] dispinterface %s;\n",
pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS1));
}
if (pClassToken->IsSet(CLASS_NONPRIMARYEVENTS2))
{
fprintf(fpIDLFile, " [source] dispinterface %s;\n",
pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS2));
}
if (pClassToken->IsSet(CLASS_NONPRIMARYEVENTS3))
{
fprintf(fpIDLFile, " [source] dispinterface %s;\n",
pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS3));
}
if (pClassToken->IsSet(CLASS_NONPRIMARYEVENTS4))
{
fprintf(fpIDLFile, " [source] dispinterface %s;\n",
pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS4));
}
// Any other interface to expose in the coclass which is part of the primary
// interface?
CTokenListWalker ChildWalker(pClassToken);
Token *pChildToken;
while (pChildToken = ChildWalker.GetNext())
{
if (pChildToken->GetType() == TYPE_IMPLEMENTS)
{
Token *pInterf;
CString szInterface;
if (!fElement)
fElement = !_stricmp((LPSTR)pChildToken->GetTagValue(IMPLEMENTS_NAME), "IHTMLElement");
szInterface = pChildToken->GetTagValue(IMPLEMENTS_NAME);
pInterf = FindInterface(szInterface);
if (pInterf)
{
// Is the interface a local one if not then don't check, we
// only need to check where interfaces are actually used.
if (FindInterfaceLocally(szInterface))
{
// If the super isn't specified and it's not a primary interface
// then error the super is required for non-primary interfaces.
if (_stricmp((LPSTR)pClassToken->GetTagValue(CLASS_INTERFACE),
(LPSTR)pInterf->GetTagValue(INTERFACE_NAME)) &&
!pInterf->IsSet(INTERFACE_SUPER) &&
!IsPrimaryInterface(szInterface))
{
char szErrorText [ MAX_LINE_LEN+1 ];
sprintf(szErrorText, "Interface %s missing super key.\n",
(LPSTR)pInterf->GetTagValue(INTERFACE_NAME));
ReportError(szErrorText);
return;
}
}
fprintf(fpIDLFile, " interface %s;\n",
(LPCSTR)pInterf->GetTagValue(INTERFACE_NAME));
}
}
}
fprintf(fpIDLFile, "};\n");
fprintf(fpIDLFile, "cpp_quote(\"EXTERN_C const GUID CLSID_%s;\")\n",
pClassToken->GetTagValue(CLASS_NAME));
if (!pClassToken->IsSet(CLASS_EVENTS) && fElement)
{
char szErrorText [ MAX_LINE_LEN+1 ];
sprintf(szErrorText, "Class %s missing events key.\n", pClassToken->GetTagValue(CLASS_NAME));
ReportError(szErrorText);
return;
}
}
void CPDLParser::GenerateEnumDescIDL ( Token *pEnumToken )
{
Token *pEvalToken;
CString szName;
fprintf ( fpIDLFile, "\ntypedef [uuid(%s)] enum _%s {\n" ,
pEnumToken -> GetTagValue ( ENUM_GUID ),
pEnumToken -> GetTagValue ( ENUM_NAME ) );
CTokenListWalker EvalChildList ( pEnumToken );
while ( pEvalToken = EvalChildList.GetNext() )
{
if ( pEvalToken -> IsSet ( EVAL_ODLNAME ) )
{
szName = pEvalToken -> GetTagValue ( EVAL_ODLNAME );
}
else
{
szName = pEnumToken -> GetTagValue ( ENUM_NAME );
szName += pEvalToken -> GetTagValue ( EVAL_NAME );
}
fprintf ( fpIDLFile, " [helpstring(\"%s\")] %s = %s,\n",
pEvalToken -> IsSet ( EVAL_STRING ) ?
pEvalToken -> GetTagValue ( EVAL_STRING ) :
pEvalToken -> GetTagValue ( EVAL_NAME ),
(LPCSTR)szName,
pEvalToken -> GetTagValue ( EVAL_VALUE ) );
}
fprintf ( fpIDLFile, "}%s;\n",
pEnumToken -> GetTagValue ( ENUM_NAME ) );
}
void CPDLParser::ReportError ( LPCSTR szErrorString )
{
printf ( "%s(0) : error PDL0000: %s", _pszPDLFileName, szErrorString);
fprintf ( fpLOGFile, "%s(0) : error PDL0000: %s", _pszPDLFileName, szErrorString );
}
void CPDLParser::GenerateHeaderFile ( void )
{
CTokenListWalker ThisFileList ( pRuntimeList, _pszPDLFileName );
Token *pImportToken;
Token *pInterfaceToken;
Token *pClassToken;
Token *pEnumToken;
Token *pStructToken;
char *pStr;
CString szCoClassName;
char szName [ MAX_LINE_LEN+1 ];
CString szInterfaceName;
strcpy ( szName, _pszPDLFileName );
pStr = strstr ( szName, "." );
if ( pStr )
*pStr = '\0';
_strlwr ( szName );
fprintf ( fpHeaderFile, "#ifndef __%s_h__\n", szName );
fprintf ( fpHeaderFile, "#define __%s_h__\n\n", szName );
fprintf ( fpHeaderFile, "/* Forward Declarations */\n" );
fprintf ( fpHeaderFile, "\nstruct ENUMDESC;\n" );
// For each import, generate a .h include
while ( pImportToken = ThisFileList.GetNext ( TYPE_IMPORT ) )
{
fprintf ( fpHeaderFile, "\n/* header files for imported files */\n" );
GenerateIncludeStatement ( pImportToken );
}
ThisFileList.Reset();
// Forward define all the interfaces so we can have defined them in any order
while ( pInterfaceToken = ThisFileList.GetNext ( TYPE_INTERFACE ) )
{
szInterfaceName = pInterfaceToken -> GetTagValue ( INTERFACE_NAME );
if ( szInterfaceName != "IDispatch" &&
szInterfaceName != "IUnknown" )
{
fprintf ( fpHeaderFile, "\n#ifndef __%s_FWD_DEFINED__\n",
pInterfaceToken -> GetTagValue ( INTERFACE_NAME ) );
fprintf ( fpHeaderFile, "#define __%s_FWD_DEFINED__\n",
pInterfaceToken -> GetTagValue ( INTERFACE_NAME ) );
fprintf ( fpHeaderFile, "typedef interface %s %s;\n",
pInterfaceToken -> GetTagValue ( INTERFACE_NAME ),
pInterfaceToken -> GetTagValue ( INTERFACE_NAME ) ) ;
fprintf ( fpHeaderFile, "#endif /* __%s_FWD_DEFINED__ */\n",
pInterfaceToken -> GetTagValue ( INTERFACE_NAME ) );
}
}
//
// Generate all the enums
//
ThisFileList.Reset();
while ( pEnumToken = ThisFileList.GetNext ( TYPE_ENUM ) )
{
GenerateIncludeEnum(pEnumToken, TRUE);
}
//
// Generate all the structs
//
ThisFileList.Reset();
while (pStructToken = ThisFileList.GetNext(TYPE_STRUCT))
{
GenerateStruct(pStructToken, fpHeaderFile);
}
ThisFileList.Reset();
// For each interface generate an extern for the GUID &
// an interface decl
while ( pInterfaceToken = ThisFileList.GetNext ( TYPE_INTERFACE ) )
{
szInterfaceName = pInterfaceToken -> GetTagValue ( INTERFACE_NAME );
if ( szInterfaceName != "IDispatch" &&
szInterfaceName != "IUnknown" &&
!pInterfaceToken -> IsSet ( INTERFACE_ABSTRACT ) &&
pInterfaceToken -> IsSet ( INTERFACE_GUID ) )
{
GenerateIncludeInterface ( pInterfaceToken );
}
}
ThisFileList.Reset();
// For each class with a GUID, generate a GUID ref
while ( pClassToken = ThisFileList.GetNext ( TYPE_CLASS ) )
{
if ( pClassToken -> IsSet ( CLASS_GUID ) &&
!pClassToken -> IsSet ( CLASS_ABSTRACT ) )
{
pClassToken -> GetTagValueOrDefault ( szCoClassName,
CLASS_COCLASSNAME, pClassToken -> GetTagValue ( CLASS_NAME ) );
fprintf ( fpHeaderFile, "\n\nEXTERN_C const GUID GUID_%s;\n\n",
pClassToken -> GetTagValue ( CLASS_COCLASSNAME ) );
if ( HasMondoDispInterface ( pClassToken ) )
{
CString szDispName;
// Map to mondo dispinterface as default dispatch interface.
szDispName = (pClassToken->IsSet(CLASS_COCLASSNAME)) ?
pClassToken->GetTagValue (CLASS_COCLASSNAME) :
pClassToken->GetTagValue(CLASS_NAME);
fprintf(fpHeaderFile, "\n\nEXTERN_C const GUID DIID_Disp%s;\n\n",
(LPCSTR)szDispName);
}
}
// Also generate extern definitions for all propdescs in this file
GeneratePropdescExtern ( pClassToken, FALSE /* Don't recurse */ );
}
fprintf ( fpHeaderFile, "\n\n#endif /*__%s_h__*/\n\n", szName );
}
void CPDLParser::GenerateIncludeStatement ( Token *pImportToken )
{
char szText [ MAX_LINE_LEN+1 ];
char *pStr;
strcpy ( szText, pImportToken -> GetTagValue ( IMPORT_NAME ) );
if ( pStr = strstr ( szText, "." ) )
{
strcpy ( pStr, ".h" );
}
else
{
strcat ( szText, ".h" );
}
fprintf ( fpHeaderFile, "#include \"%s\"\n", szText );
}
void CPDLParser::GenerateIncludeInterface ( Token *pInterfaceToken )
{
// Only generate the C++ Form
Token *pChildToken;
Token *pArgToken;
CString szArg;
CString szProp;
BOOL fFirst;
CString szSuper;
if ( pInterfaceToken -> GetType() == TYPE_EVENT )
return;
fprintf ( fpHeaderFile, "\n#ifndef __%s_INTERFACE_DEFINED__\n",
pInterfaceToken -> GetTagValue ( INTERFACE_NAME ) );
fprintf ( fpHeaderFile, "\n#define __%s_INTERFACE_DEFINED__\n",
pInterfaceToken -> GetTagValue ( INTERFACE_NAME ) );
fprintf ( fpHeaderFile, "\nEXTERN_C const IID IID_%s;\n\n",
pInterfaceToken -> GetTagValue ( INTERFACE_NAME ) );
if (pInterfaceToken->IsSet(INTERFACE_CUSTOM) ||
!PrimaryTearoff(pInterfaceToken) ||
!_stricmp((LPCSTR)pInterfaceToken->GetTagValue(INTERFACE_NAME), "IHTMLDocument2"))
{
szSuper = pInterfaceToken->GetTagValue(INTERFACE_SUPER);
}
fprintf(fpHeaderFile, "\nMIDL_INTERFACE(\"%s\")\n%s : public %s\n{\npublic:\n",
pInterfaceToken->GetTagValue(INTERFACE_GUID),
pInterfaceToken->GetTagValue(INTERFACE_NAME),
((LPCSTR)szSuper && *(LPCSTR)szSuper) ? (LPCSTR)szSuper : "IDispatch");
CTokenListWalker ChildWalker ( pInterfaceToken );
while ( pChildToken = ChildWalker.GetNext() )
{
if ( pChildToken -> GetType() == TYPE_METHOD )
{
fprintf ( fpHeaderFile, " virtual %s STDMETHODCALLTYPE %s(\n ",
pChildToken -> GetTagValue ( METHOD_RETURNTYPE ),
pChildToken->IsSet(METHOD_SZINTERFACEEXPOSE) ?
pChildToken->GetTagValue(METHOD_SZINTERFACEEXPOSE) :
pChildToken->GetTagValue(METHOD_NAME));
fFirst = TRUE;
CTokenListWalker ArgListWalker ( pChildToken );
while ( pArgToken = ArgListWalker.GetNext() )
{
if ( !fFirst )
fprintf ( fpHeaderFile, "," );
szArg = "";
pArgToken -> AddParam ( szArg, METHODARG_IN, "in" );
pArgToken -> AddParam ( szArg, METHODARG_OUT, "out" );
fprintf ( fpHeaderFile, "/* [%s] */ %s %s", (LPCSTR)szArg,
// Fixing a bug in the old code
// Should realy get the atype - allow the type if atype not set
ConvertType(pArgToken -> IsSet ( METHODARG_ATYPE ) ?
pArgToken -> GetTagValue ( METHODARG_ATYPE ) :
pArgToken -> GetTagValue ( METHODARG_TYPE )),
pArgToken -> GetTagValue ( METHODARG_ARGNAME ) );
fFirst = FALSE;
}
fprintf ( fpHeaderFile, ") = 0;\n\n" );
}
else
{
// Property
ComputePropType(pChildToken, szProp, TRUE);
if ( pChildToken -> IsSet ( PROPERTY_SET ))
{
fprintf ( fpHeaderFile, " virtual HRESULT STDMETHODCALLTYPE put_%s(\n %s /* [in] */ %s v) = 0;\n\n",
pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
(LPSTR)pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
(LPSTR)pChildToken->GetTagValue(PROPERTY_NAME),
(LPCSTR)szProp,
pChildToken -> GetTagValue ( PROPERTY_ATYPE));
}
if ( pChildToken -> IsSet ( PROPERTY_GET ))
{
fprintf ( fpHeaderFile,
" virtual HRESULT STDMETHODCALLTYPE get_%s(\n %s /* [out] */ %s * p) = 0;\n\n",
pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
(LPSTR)pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
(LPSTR)pChildToken->GetTagValue(PROPERTY_NAME),
(LPCSTR)szProp,
pChildToken -> GetTagValue ( PROPERTY_ATYPE) );
}
}
}
fprintf ( fpHeaderFile, "};\n\n" );
fprintf ( fpHeaderFile, "#endif /* __%s_INTERFACE_DEFINED__ */\n\n",
pInterfaceToken -> GetTagValue ( INTERFACE_NAME ) );
}
void CPDLParser::GenerateIncludeEnum(
Token *pEnumToken, BOOL fSpitExtern, FILE *pFile)
{
Token *pEvalToken;
if (!pFile)
{
pFile = fpHeaderFile;
}
fprintf(pFile, "typedef enum _%s\n{\n" ,
pEnumToken -> GetTagValue ( ENUM_NAME ) );
CTokenListWalker EvalChildList ( pEnumToken );
while ( pEvalToken = EvalChildList.GetNext() )
{
fprintf(pFile, " %s%s = %s,\n",
pEnumToken -> GetTagValue(ENUM_PREFIX),
pEvalToken -> GetTagValue(EVAL_NAME),
pEvalToken -> GetTagValue(EVAL_VALUE));
}
// Add an _Max for the MAC build - apparently the mac needs
// this to indicate that it's an integer
fprintf(pFile, " %s_Max = 2147483647L\n",
pEnumToken -> GetTagValue ( ENUM_NAME ) );
fprintf(pFile, "} %s;\n\n",
pEnumToken -> GetTagValue ( ENUM_NAME ) );
if (fSpitExtern)
{
// Generate an EXTERN from the enum descriptor so other hdls only have to include
// the .h file.
fprintf(pFile, "\nEXTERN_C const ENUMDESC s_enumdesc%s;\n\n",
pEnumToken->GetTagValue ( ENUM_NAME ) );
}
}
void
CPDLParser::GenerateStruct(Token *pStructToken, FILE *pFile)
{
Token *pMemberToken;
fprintf(pFile, "typedef struct _%s\n{\n" ,
pStructToken->GetTagValue(STRUCT_NAME));
CTokenListWalker ChildList(pStructToken);
while (pMemberToken = ChildList.GetNext())
{
fprintf(pFile, " %s %s;\n",
pMemberToken->GetTagValue(STRUCTMEMBER_TYPE),
pMemberToken->GetTagValue(STRUCTMEMBER_NAME));
}
fprintf(pFile, "} %s;\n\n",
pStructToken->GetTagValue(STRUCT_NAME));
}
BOOL CPDLParser::AddType ( LPCSTR szTypeName, LPCSTR szHandler )
{
Token *pTypeToken = pDynamicTypeList->AddNewToken ( (DESCRIPTOR_TYPE)TYPE_DATATYPE );
if ( pTypeToken == NULL )
return FALSE;
if ( !pTypeToken->AddTag ( DATATYPE_NAME, szTypeName ) )
return FALSE;
return pTypeToken->AddTag ( DATATYPE_HANDLER, szHandler );
}
BOOL CPDLParser::AddEventType ( LPCSTR szTypeName, LPCSTR szVTSType )
{
Token *pTypeToken = pDynamicEventTypeList->AddNewToken ( (DESCRIPTOR_TYPE)TYPE_DATATYPE );
if ( pTypeToken == NULL )
return FALSE;
if ( !pTypeToken->AddTag ( DATATYPE_NAME, szTypeName ) )
return FALSE;
return pTypeToken->AddTag ( DATATYPE_HANDLER, szVTSType );
}
BOOL CPDLParser::LookupType ( LPCSTR szTypeName, CString &szIntoString,
CString &szFnPrefix, StorageType *pStorageType /* = NULL */ )
{
Token *pTypeToken;
UINT uIndex;
// Look in the static array first
if ( ( uIndex = szIntoString.Lookup ( DataTypes, szTypeName ) ) != (UINT)-1 )
{
if ( pStorageType )
{
*pStorageType = DataTypes [ uIndex ].stStorageType;
szFnPrefix = DataTypes [ uIndex ].szMethodFnPrefix;
}
return TRUE;
}
// Look finaly in the dynamic array
CTokenListWalker TypeList ( pDynamicTypeList );
if ( pTypeToken = TypeList.GetNext ( (DESCRIPTOR_TYPE)TYPE_DATATYPE, szTypeName ) )
{
szIntoString = pTypeToken->GetTagValue ( DATATYPE_HANDLER );
if ( pStorageType )
{
// In the dynamic array are either enums iface ptrs or class ptrs
// All can be stored in a DWORD, so ...
*pStorageType = STORAGETYPE_NUMBER;
}
return TRUE;
}
else
{
return FALSE;
}
}
BOOL CPDLParser::LookupEventType ( CString &szIntoString, LPCSTR szTypeName )
{
Token *pTypeToken;
// Look in the static array first
if ( szIntoString.Lookup ( vt, szTypeName ) != (UINT)-1 )
{
return TRUE;
}
// Look finaly in the dynamic array
CTokenListWalker TypeList ( pDynamicEventTypeList );
if ( pTypeToken = TypeList.GetNext ( (DESCRIPTOR_TYPE)TYPE_DATATYPE, szTypeName ) )
{
szIntoString = pTypeToken->GetTagValue ( DATATYPE_HANDLER );
return TRUE;
}
else
{
return FALSE;
}
}
UINT uProps [] =
{
PROPERTY_MEMBER,
PROPERTY_ABSTRACT,
PROPERTY_GETSETMETHODS,
PROPERTY_CAA,
PROPERTY_SUBOBJECT
};
// Legal combinations of properties
static struct
{
UINT uID1;
UINT uID2;
UINT uID3;
UINT uMask;
} PropertyCheck [] =
{
{ PROPERTY_MEMBER, (UINT)-1,(UINT)-1 },
{ PROPERTY_SUBOBJECT, (UINT)-1 ,(UINT)-1 },
{ PROPERTY_SUBOBJECT, PROPERTY_MEMBER,(UINT)-1 },
{ PROPERTY_GETSETMETHODS, (UINT)-1,(UINT)-1 },
{ PROPERTY_ABSTRACT, (UINT)-1,(UINT)-1},
{ PROPERTY_CAA, (UINT)-1,(UINT)-1 },
{ PROPERTY_SUBOBJECT, PROPERTY_CAA,(UINT)-1 },
};
void CPDLParser::Init ( void )
{
UINT i,j;
for ( i = 0 ; i < ARRAY_SIZE ( PropertyCheck ) ; i++ )
{
PropertyCheck [ i ].uMask = 0;
for ( j = 0 ; j < ARRAY_SIZE ( uProps ) ; j++ )
{
if ( PropertyCheck [ i ].uID1 == uProps [ j ] )
{
PropertyCheck [ i ].uMask |= 1<<j;
}
else if ( PropertyCheck [ i ].uID2 == uProps [ j ] )
{
PropertyCheck [ i ].uMask |= 1<<j;
}
else if ( PropertyCheck [ i ].uID3 == uProps [ j ] )
{
PropertyCheck [ i ].uMask |= 1<<j;
}
}
}
}
BOOL CPDLParser::PatchPropertyTypes ( void )
{
// For each property declaration, set the object flag if the
// Handler for the type is object
CTokenListWalker WholeList ( pRuntimeList );
Token *pToken;
Token *pChildToken;
CString szHandler;
CString szFnPrefix;
CString szAType;
CString szName;
BOOL fMatched;
char szErrorText [ MAX_LINE_LEN+1 ];
UINT i;
UINT uMask;
while ( pToken = WholeList.GetNext() )
{
if ( pToken -> GetType() == TYPE_EVENT ||
pToken -> GetType() == TYPE_CLASS ||
pToken -> GetType() == TYPE_INTERFACE )
{
if ( pToken -> GetType() == TYPE_CLASS )
{
// Has it got a super, if so is it referenced
if ( pToken -> IsSet ( CLASS_SUPER ) )
{
CTokenListWalker AllList ( pRuntimeList );
if ( !AllList.GetNext ( TYPE_CLASS, pToken -> GetTagValue ( CLASS_SUPER ) ) )
{
sprintf ( szErrorText, "Class %s References unknown super:%s\n",
(LPCSTR)pToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pToken->GetTagValue ( CLASS_SUPER ) );
ReportError ( szErrorText );
return FALSE;
}
}
if ( pToken -> IsSet ( CLASS_INTERFACE ) )
{
CTokenListWalker AllList ( pRuntimeList );
if ( !AllList.GetNext ( TYPE_INTERFACE, pToken -> GetTagValue ( CLASS_INTERFACE ) ) )
{
sprintf ( szErrorText, "Class %s References unknown interface:%s\n",
(LPCSTR)pToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pToken->GetTagValue ( CLASS_INTERFACE ) );
ReportError ( szErrorText );
return FALSE;
}
}
if ( pToken -> IsSet ( CLASS_EVENTS ) )
{
CTokenListWalker AllList ( pRuntimeList );
if ( !AllList.GetNext ( TYPE_EVENT, pToken -> GetTagValue ( CLASS_EVENTS ) ) )
{
sprintf ( szErrorText, "Class %s References unknown events:%s\n",
(LPCSTR)pToken->GetTagValue ( CLASS_NAME ),
(LPCSTR)pToken->GetTagValue ( CLASS_EVENTS ) );
ReportError ( szErrorText );
return FALSE;
}
}
// If you have an event set , you must have a coclass
if ( pToken -> IsSet ( CLASS_EVENTS ) && !pToken -> IsSet ( CLASS_ABSTRACT ) &&
!pToken -> IsSet ( CLASS_GUID ) )
{
sprintf ( szErrorText, "Non abstract class %s has an event set but no GUID\n",
(LPCSTR)pToken->GetTagValue ( CLASS_NAME ) );
ReportError ( szErrorText );
return FALSE;
}
}
else if ( pToken -> GetType() == TYPE_INTERFACE )
{
if ( pToken -> IsSet ( INTERFACE_SUPER ) )
{
CTokenListWalker AllList ( pRuntimeList );
if ( !AllList.GetNext ( TYPE_INTERFACE, pToken -> GetTagValue ( INTERFACE_SUPER ) ) )
{
sprintf ( szErrorText, "Interface %s References unknown super:%s\n",
(LPCSTR)pToken->GetTagValue ( INTERFACE_NAME ),
(LPCSTR)pToken->GetTagValue ( INTERFACE_SUPER ) );
ReportError ( szErrorText );
return FALSE;
}
}
}
else if ( pToken -> GetType() == TYPE_EVENT )
{
if ( pToken -> IsSet ( EVENT_SUPER ) )
{
CTokenListWalker AllList ( pRuntimeList );
if ( !AllList.GetNext ( TYPE_EVENT, pToken -> GetTagValue ( EVENT_SUPER ) ) )
{
sprintf ( szErrorText, "Events %s References unknown super:%s\n",
(LPCSTR)pToken->GetTagValue ( EVENT_NAME ),
(LPCSTR)pToken->GetTagValue ( EVENT_SUPER ) );
ReportError ( szErrorText );
return FALSE;
}
}
}
CTokenListWalker ChildList ( pToken );
while ( pChildToken = ChildList.GetNext() )
{
if ( pChildToken -> GetType() == TYPE_PROPERTY )
{
// If the Type field is not set, which it won't be for many
// abstract properties, set it to the ATYPE. We still
// need the type to determine if the property is an object value
// property
if ( !pChildToken -> IsSet ( PROPERTY_TYPE ) )
{
pChildToken -> AddTag ( PROPERTY_TYPE,
pChildToken -> GetTagValue ( PROPERTY_ATYPE ) );
}
if ( !LookupType ( pChildToken -> GetTagValue ( PROPERTY_TYPE ),
szHandler, szFnPrefix ) )
{
// Seeing as we don't use the handler for abstract types, we
// allow the lookup to fail
if ( !pChildToken -> IsSet ( PROPERTY_ABSTRACT ) )
{
sprintf ( szErrorText, "Invalid Type:%s in %s Property:%s\n",
(LPCSTR)pChildToken->GetTagValue ( PROPERTY_TYPE ),
(LPCSTR)pToken->GetTagValue ( NAME_TAG ),
(LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ) );
ReportError ( szErrorText );
return FALSE;
}
}
// Currently we insist that you automate enums as BSTR's
szAType = pChildToken->GetTagValue ( PROPERTY_ATYPE );
if ( szHandler == "Enum" && szAType != "BSTR" )
{
sprintf ( szErrorText, "You must set atype:BSTR for an enum property %s : Property:%s\n",
(LPCSTR)pToken->GetTagValue ( NAME_TAG ),
(LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ) );
ReportError ( szErrorText );
return FALSE;
}
if ( szHandler == "Color" && szAType != "VARIANT" )
{
sprintf ( szErrorText, "You must set atype:VARIANT for an type:CColorValue property %s : Property:%s\n",
(LPCSTR)pToken->GetTagValue ( NAME_TAG ),
(LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ) );
ReportError ( szErrorText );
return FALSE;
}
if ( szHandler == "object" &&
!pChildToken -> IsSet ( PROPERTY_OBJECT ) )
{
pChildToken -> Set ( PROPERTY_OBJECT );
}
// Object valued properties must always be abstract because we don't have
// the notion of an "ObjectHandler"
if ( pChildToken -> IsSet ( PROPERTY_OBJECT ) &&
!pChildToken -> IsSet ( PROPERTY_ABSTRACT ) )
{
sprintf ( szErrorText, "Object Type Property %s:%s MUST be abstract\n",
(LPCSTR)pToken->GetTagValue ( NAME_TAG ),
(LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ) );
ReportError ( szErrorText );
return FALSE;
}
for ( i = 0, uMask = 0 ; i < ARRAY_SIZE ( uProps ) ; i++ )
{
if ( pChildToken -> IsSet ( uProps [ i ] ) )
{
uMask |= 1<<i;
}
}
for ( i = 0, fMatched = FALSE;
i < ARRAY_SIZE ( PropertyCheck ); i++ )
{
if ( PropertyCheck [ i ].uMask == uMask )
{
fMatched = TRUE;
}
}
if ( !fMatched )
{
sprintf ( szErrorText, "Invalid combination of member/method/abstract/caa on %s:%s\n",
(LPCSTR)pToken->GetTagValue ( NAME_TAG ),
(LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ) );
ReportError ( szErrorText );
return FALSE;
}
// Subobject MUST have a GET and MUST NOT have a SET
if ( pChildToken -> IsSet ( PROPERTY_SUBOBJECT ) &&
( !pChildToken -> IsSet ( PROPERTY_GET ) || pChildToken -> IsSet ( PROPERTY_SET ) ) )
{
sprintf ( szErrorText, "Invalid combination of subobject/get/set on %s:%s\n",
(LPCSTR)pToken->GetTagValue ( NAME_TAG ),
(LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ) );
ReportError ( szErrorText );
return FALSE;
}
// DISPLAYBIND Always implies BINDABLE - so always set it
if ( pChildToken -> IsSet ( PROPERTY_DISPLAYBIND ) &&
!pChildToken -> IsSet ( PROPERTY_BINDABLE ) )
{
pChildToken -> Set ( PROPERTY_BINDABLE );
}
// For now we limit the enum: type to atypre:VARIANT,
if ( pChildToken -> IsSet ( PROPERTY_ENUMREF ) )
{
if ( szAType != "VARIANT" )
{
sprintf ( szErrorText, "Invalid combination of atype/enum on %s:%s\n",
(LPCSTR)pToken->GetTagValue ( NAME_TAG ),
(LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ) );
ReportError ( szErrorText );
return FALSE;
}
}
// Set an internal flag if the property cascades - saves looking this up later
if ( pChildToken -> IsSet ( PROPERTY_CAA ) )
{
const CCachedAttrArrayInfo *pCCAAI = GetCachedAttrArrayInfo( (LPCSTR)pChildToken -> GetTagValue ( PROPERTY_DISPID ) );
if ( pCCAAI->szDispId != NULL )
{
pChildToken -> Set ( PROPERTY_CASCADED );
}
}
if ( !pChildToken -> IsSet ( PROPERTY_DISPID ) )
{
sprintf ( szErrorText, "Missing compulsory attribute 'dispid' on %s:%s\n",
(LPCSTR)pToken->GetTagValue ( NAME_TAG ),
(LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ) );
ReportError ( szErrorText );
}
// SETATDESIGNTIME augments regular set
if ( pChildToken -> IsSet ( PROPERTY_SETDESIGNMODE ) )
{
pChildToken -> Set ( PROPERTY_SET );
}
}
else if ( pChildToken -> GetType() == TYPE_METHOD )
{
Token *pArgToken;
// For each method arg check
// that type is VARIANT if a optional tag is specified
CTokenListWalker ArgListWalker ( pChildToken );
while ( pArgToken = ArgListWalker.GetNext() )
{
szAType = pArgToken->GetTagValue ( METHODARG_TYPE );
if ( pArgToken->IsSet ( METHODARG_OPTIONAL ) &&
!(szAType == "VARIANT" || szAType == "VARIANT*") )
{
// MIDL will let this through but you'd never be able to
// set the default
sprintf ( szErrorText, "Method arg type must be VARIANT with optional: tag on %s:%s\n",
(LPCSTR)pToken->GetTagValue ( NAME_TAG ),
(LPCSTR)pChildToken->GetTagValue ( METHOD_NAME ) );
ReportError ( szErrorText );
return FALSE;
}
if ( LookupType ( pArgToken -> GetTagValue ( METHODARG_TYPE ),
szHandler, szFnPrefix ) )
{
if (szHandler == "Enum" &&
!(pToken->GetType() == TYPE_INTERFACE &&
pToken->IsSet(INTERFACE_CUSTOM)))
{
sprintf ( szErrorText, "You must set type:BSTR for an enum %s Method:%s arg:%s\n",
(LPCSTR)pToken->GetTagValue ( NAME_TAG ),
(LPCSTR)pChildToken->GetTagValue ( METHOD_NAME ),
(LPCSTR)pArgToken->GetTagValue ( METHODARG_ARGNAME ) );
ReportError ( szErrorText );
return FALSE;
}
}
}
}
}
}
}
return TRUE;
}
//
// Patch up all interfaces which are not a primary default interfaces tearoff
// and mark as such (NOPRIMARY). Classes marked as NOPRIMARY will be derived
// from the inheritance chain instead of being derived from IDispatch.
//
BOOL
CPDLParser::PatchInterfaces ()
{
CTokenListWalker ThisFilesList(pRuntimeList, _pszPDLFileName);
Token *pClassToken;
Token *pInterf;
while (pClassToken = ThisFilesList.GetNext(TYPE_CLASS))
{
CString szInterface;
szInterface = pClassToken->GetTagValue(CLASS_INTERFACE);
if (!FindTearoff(pClassToken->GetTagValue(CLASS_NAME),
(LPCSTR)szInterface))
{
CString szInterfSuper;
pInterf = FindInterface(szInterface);
while (pInterf)
{
pInterf->Set(INTERFACE_NOPRIMARYTEAROFF);
szInterfSuper = pInterf->GetTagValue(INTERFACE_SUPER);
pInterf = FindInterface(szInterfSuper);
}
}
}
return TRUE;
}
const CCachedAttrArrayInfo*
CPDLParser::GetCachedAttrArrayInfo( LPCSTR szDispId )
{
CCachedAttrArrayInfo *pCCAAI = rgCachedAttrArrayInfo;
while (pCCAAI->szDispId)
{
if (0==strcmp(szDispId, pCCAAI->szDispId))
return pCCAAI;
++pCCAAI;
}
//This is means it is not applied to a XF structure
return pCCAAI;
}
BOOL CPDLParser::GenerateHTMFile ()
{
Token *pToken;
CTokenListWalker WholeList ( pRuntimeList );
CTokenListWalker ThisFilesList ( pRuntimeList, _pszPDLFileName );
fprintf ( fpHTMFile, "<HTML>\n" );
fprintf ( fpHTMFile, "<HEAD>\n" );
fprintf ( fpHTMFile, "<TITLE>Interface Documentation from %s</TITLE>\n", _pszPDLFileName );
fprintf ( fpHTMFile, "</HEAD>\n" );
fprintf ( fpHTMFile, "<BODY>\n" );
fprintf ( fpHTMFile, "<P>\n" );
while ( pToken = ThisFilesList.GetNext ( TYPE_ENUM ) )
{
if ( !pToken -> IsSet ( ENUM_HIDDEN ))
{
fprintf ( fpHTMFile, "<B><U>Enumerations:</U></B> %s\n",
pToken->GetTagValue ( ENUM_NAME ) );
fprintf ( fpHTMFile, "<P>\n" );
fprintf ( fpHTMFile, "<TABLE WIDTH=70%%>\n" );
fprintf ( fpHTMFile, "<TR>\n" );
fprintf ( fpHTMFile, "<TH WIDTH=50%% ALIGN=\"Left\">Name</TH>\n" );
fprintf ( fpHTMFile, "<TH WIDTH=25%% ALIGN=\"Center\">String</TH>\n" );
fprintf ( fpHTMFile, "</TR>\n" );
GenerateEnumHTM ( pToken,
pToken -> IsSet ( ENUM_PREFIX ) ?
pToken->GetTagValue ( ENUM_PREFIX ) :
pToken->GetTagValue ( ENUM_NAME ) ); // sort enums
fprintf ( fpHTMFile, "</TABLE>\n" );
fprintf ( fpHTMFile, "<P>\n" );
}
}
// Output interface documentation
ThisFilesList.Reset();
while ( (pToken = ThisFilesList.GetNext ( TYPE_INTERFACE )) )
{
if (_stricmp("IUnknown", pToken->GetTagValue ( INTERFACE_NAME )) &&
_stricmp("IDispatch", pToken->GetTagValue ( INTERFACE_NAME )) )
{
char achFilePrefix[100];
strcpy (achFilePrefix, _pszPDLFileName);
char *pDot = strchr(achFilePrefix, '.');
if (pDot) {
*pDot = '\0';
}
else {
strcpy(achFilePrefix, "badpdl");
}
fprintf ( fpHTMIndexFile, "<A NAME=\"Index_Interface_%s\">Interface: <A HREF=\"%s.htm#Interface_%s\">%s</A><BR>\n",
pToken->GetTagValue ( INTERFACE_NAME ),
achFilePrefix, pToken->GetTagValue ( INTERFACE_NAME ),
pToken->GetTagValue ( INTERFACE_NAME ));
fprintf ( fpHTMFile, "<P>\n" );
fprintf ( fpHTMFile, "<A NAME=\"Interface_%s\">\n", pToken->GetTagValue ( INTERFACE_NAME ) );
fprintf ( fpHTMFile, "<TABLE>\n" );
fprintf ( fpHTMFile, "<TR><TD><H1>Interface</H1></TD>"
"<TR><TD><B>%s</B></TD><TD> GUID: </TD><TD>%s</TD></TR>"
"<TR><TD>inherits from interface</TD></TR>"
"<TR><TD><B><A HREF=\"AllIndex.htm#Index_Interface_%s\">%s</A></B></TD></TR>\n"
"</TABLE>\n",
pToken->GetTagValue ( INTERFACE_NAME ),
pToken->GetTagValue ( INTERFACE_GUID ),
pToken->GetTagValue ( INTERFACE_SUPER ),
pToken->GetTagValue ( INTERFACE_SUPER ) );
fprintf ( fpHTMFile, "<P>\n" );
fprintf ( fpHTMFile, "<HR>\n" );
fprintf ( fpHTMFile, "<H2>Properties</H2>\n" );
fprintf ( fpHTMFile, "<TABLE>\n" );
fprintf ( fpHTMFile, "<TR>" );
fprintf ( fpHTMFile, "<TH>Name</TH>" );
fprintf ( fpHTMFile, "<TH>AType</TH>" );
fprintf ( fpHTMFile, "<TH>DISPID</TH>" );
fprintf ( fpHTMFile, "<TH>G</TH>" );
fprintf ( fpHTMFile, "<TH>S</TH>" );
fprintf ( fpHTMFile, "<TH>DT</TH>" );
fprintf ( fpHTMFile, "<TH>Default</TH>" );
fprintf ( fpHTMFile, "<TH>Min</TH>" );
fprintf ( fpHTMFile, "<TH>Max</TH>" );
fprintf ( fpHTMFile, "</TR>\n" );
GenerateInterfacePropertiesHTM ( pToken ); // sort attributes
fprintf ( fpHTMFile, "</TABLE>" );
fprintf ( fpHTMFile, "<H2>Methods</H2>\n" );
fprintf ( fpHTMFile, "<TABLE BORDER=1>\n" );
fprintf ( fpHTMFile, "<TR>" );
fprintf ( fpHTMFile, "<TH>Ret. Name</TH>" );
fprintf ( fpHTMFile, "<TH>Name</TH>" );
fprintf ( fpHTMFile, "<TH>Param Dir</TH>" );
fprintf ( fpHTMFile, "<TH>Param Type</TH>" );
fprintf ( fpHTMFile, "<TH>Param Name</TH>" );
fprintf ( fpHTMFile, "<TH>Default Value</TH>" );
fprintf ( fpHTMFile, "<TH>Optional</TH>" );
fprintf ( fpHTMFile, "<TH>Ret. Type</TH>" );
fprintf ( fpHTMFile, "</TR>\n" );
GenerateInterfaceMethodHTM ( pToken ); // sort attributes
fprintf ( fpHTMFile, "</TABLE>" );
}
}
// Output eventset documentation
ThisFilesList.Reset();
while ( (pToken = ThisFilesList.GetNext ( TYPE_EVENT )) )
{
if (_stricmp("IDispatch", pToken->GetTagValue ( INTERFACE_NAME )) )
{
char achFilePrefix[100];
strcpy (achFilePrefix, _pszPDLFileName);
char *pDot = strchr(achFilePrefix, '.');
if (pDot) {
*pDot = '\0';
}
else {
strcpy(achFilePrefix, "badpdl");
}
fprintf ( fpHTMIndexFile, "<A NAME=\"Index_Eventset_%s\">Eventset: <A HREF=\"%s.htm#Eventset_%s\">%s</A><BR>\n",
pToken->GetTagValue ( EVENT_NAME ),
achFilePrefix, pToken->GetTagValue ( EVENT_NAME ),
pToken->GetTagValue ( EVENT_NAME ));
fprintf ( fpHTMFile, "<BR><BR>\n" );
fprintf ( fpHTMFile, "<A NAME=\"Eventset_%s\">\n", pToken->GetTagValue ( EVENT_NAME ) );
fprintf ( fpHTMFile, "<TABLE>\n" );
fprintf ( fpHTMFile, "<TR><TD><H1>Event Set</H1></TD>"
"<TR><TD><B>%s</B></TD><TD> GUID: </TD><TD>%s</TD></TR>"
"<TR><TD>inherits from event set</TD></TR>"
"<TR><TD><B><A HREF=\"AllIndex.htm#Index_Eventset_%s\">%s</A></B></TD></TR>\n"
"</TABLE>\n",
pToken->GetTagValue ( EVENT_NAME ),
pToken->GetTagValue ( EVENT_GUID ),
pToken->GetTagValue ( EVENT_SUPER ),
pToken->GetTagValue ( EVENT_SUPER ) );
fprintf ( fpHTMFile, "<HR>\n" );
fprintf ( fpHTMFile, "<H2>Methods</H2>\n" );
fprintf ( fpHTMFile, "<TABLE BORDER=1>\n" );
fprintf ( fpHTMFile, "<TR>" );
fprintf ( fpHTMFile, "<TH>Ret. Name</TH>" );
fprintf ( fpHTMFile, "<TH>Name</TH>" );
fprintf ( fpHTMFile, "<TH>DISPID</TH>" );
fprintf ( fpHTMFile, "<TH>Cancelable</TH>" );
fprintf ( fpHTMFile, "<TH>Bubbling</TH>" );
fprintf ( fpHTMFile, "<TH>Param Dir</TH>" );
fprintf ( fpHTMFile, "<TH>Param Type</TH>" );
fprintf ( fpHTMFile, "<TH>Param Name</TH>" );
fprintf ( fpHTMFile, "<TH>Default Value</TH>" );
fprintf ( fpHTMFile, "<TH>Optional</TH>" );
fprintf ( fpHTMFile, "<TH>Ret. Type</TH>" );
fprintf ( fpHTMFile, "</TR>\n" );
GenerateEventMethodHTM ( pToken ); // sort attributes
fprintf ( fpHTMFile, "</TABLE>" );
}
}
fprintf ( fpHTMFile, "</BODY>\n");
fprintf ( fpHTMFile, "</HTML>\n");
return TRUE;
}
void CPDLParser::GenerateArg ( Token *pArgToken )
{
if ( ! pArgToken -> IsSet ( METHODARG_RETURNVALUE ) )
{
fprintf ( fpHTMFile, "&nbsp[%s] %s %s",
pArgToken -> IsSet ( METHODARG_OUT ) ? "out" : "in",
pArgToken -> GetTagValue ( METHODARG_TYPE ),
pArgToken -> GetTagValue ( METHODARG_ARGNAME ) );
if ( pArgToken -> IsSet ( METHODARG_DEFAULTVALUE ) )
{
fprintf ( fpHTMFile, "=%s",
pArgToken -> GetTagValue ( METHODARG_DEFAULTVALUE ) );
}
if ( pArgToken -> IsSet ( METHODARG_OPTIONAL ) )
{
fprintf ( fpHTMFile, " [optional]" );
}
}
}
void CPDLParser::GenerateInterfaceArg ( Token *pArgToken )
{
if ( ! pArgToken -> IsSet ( METHODARG_RETURNVALUE ) )
{
fprintf ( fpHTMFile, "<TD>%s</TD><TD>%s</TD><TD>%s</TD>",
pArgToken -> IsSet ( METHODARG_OUT ) ? "out" : "in",
pArgToken -> GetTagValue ( METHODARG_TYPE ),
pArgToken -> GetTagValue ( METHODARG_ARGNAME ) );
fprintf ( fpHTMFile, "<TD>%s</TD><TD>%s</TD>",
pArgToken -> IsSet ( METHODARG_DEFAULTVALUE ) ?
(pArgToken -> GetTagValue ( METHODARG_DEFAULTVALUE )) : "",
pArgToken -> IsSet ( METHODARG_OPTIONAL) ?
"Y" : "N" );
}
}
void CPDLParser::GenerateMethodHTM ( Token *pIntfToken )
{
CTokenListWalker *pChildList;
Token *pChildToken;
Token *pArgToken;
int cArgs;
CString szSuper;
CTokenListWalker *ptlw = NULL;
pChildList = new CTokenListWalker ( pIntfToken );
szSuper = pIntfToken->GetTagValue ( INTERFACE_SUPER );
do
{
while ( pChildToken = pChildList -> GetNext() )
{
CString szRetValArg;
CString szRetValType;
CTokenListWalker ArgListWalker ( pChildToken );
cArgs = 0;
// Loop thru all arguments.
while ( (pArgToken = ArgListWalker.GetNext()) != NULL &&
pArgToken -> GetType () == TYPE_METHOD_ARG )
{
// Looking for a return value.
if ( pArgToken -> IsSet ( METHODARG_RETURNVALUE ) )
{
// If a return value exist then get the argument name.
szRetValArg = pArgToken -> GetTagValue (
pArgToken -> IsSet ( METHODARG_ARGNAME ) ?
METHODARG_ARGNAME : METHODARG_RETURNVALUE );
szRetValType = pArgToken -> GetTagValue ( METHODARG_TYPE );
}
else
{
cArgs++;
}
}
if ( strlen ( szRetValArg ) )
{
fprintf ( fpHTMFile, "<TR><TD>%s = <I>object.</I><B>%s</B>",
(LPCSTR)szRetValArg,
pChildToken -> GetTagValue ( METHOD_NAME ) );
}
else
{
fprintf ( fpHTMFile, "<TR><TD><I>object.</I><B>%s</B>",
pChildToken -> GetTagValue ( METHOD_NAME ) );
}
int cArgIndex = 0;
ArgListWalker.Reset ( );
while ( ( pArgToken = ArgListWalker.GetNext ( ) ) != NULL &&
pArgToken -> GetType () == TYPE_METHOD_ARG )
{
if ( ! pArgToken -> IsSet ( METHODARG_RETURNVALUE ) )
{
if (cArgIndex == 0)
{
switch (cArgs)
{
case 0:
fprintf ( fpHTMFile, "<TD>( )</TD>\n" );
fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
(LPCSTR)szRetValType );
fprintf ( fpHTMFile, "</TR>\n" );
break;
case 1:
fprintf ( fpHTMFile, "<TD>(" );
GenerateArg( pArgToken );
fprintf ( fpHTMFile, "&nbsp)</TD>\n" );
fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
(LPCSTR)szRetValType );
fprintf ( fpHTMFile, "</TR>\n" );
break;
default:
fprintf ( fpHTMFile, "<TD>(" );
GenerateArg( pArgToken );
fprintf ( fpHTMFile, ",</TD>\n" );
fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
(LPCSTR)szRetValType );
fprintf ( fpHTMFile, "</TR>\n" );
break;
}
}
else
{
if (cArgIndex > 1)
{
fprintf ( fpHTMFile, ",</TD></TR>\n" );
}
fprintf ( fpHTMFile, "<TR><TD></TD><TD>&nbsp" );
GenerateArg( pArgToken );
}
cArgIndex++;
}
}
if ( cArgIndex == 0 )
{
fprintf ( fpHTMFile, "<TD>( )</TD>\n" );
fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
(LPCSTR)szRetValType );
fprintf ( fpHTMFile, "</TR>\n" );
}
else if ( cArgIndex > 1 )
{
fprintf ( fpHTMFile, ")</TD></TR>\n" );
}
fprintf ( fpHTMFile, "<TR>&nbsp</TR>" );
}
// Get inherited interface.
if ( strlen ( szSuper ) )
{
if (ptlw == NULL)
{
ptlw = new CTokenListWalker ( pRuntimeList, _pszPDLFileName );
}
else
{
ptlw->Reset();
}
TryAgain:
pIntfToken = ptlw->GetNext ( TYPE_INTERFACE, szSuper );
if (pIntfToken)
{
szSuper = pIntfToken->GetTagValue ( INTERFACE_SUPER );
delete pChildList;
pChildList = new CTokenListWalker ( pIntfToken );
}
else
{
if ( !ptlw->IsGenericWalker ( ) )
{
delete ptlw;
ptlw = new CTokenListWalker ( pRuntimeList );
goto TryAgain;
}
}
}
else
{
break;
}
} while (pIntfToken);
delete pChildList;
delete ptlw;
}
void CPDLParser::GenerateInterfaceMethodHTM ( Token *pIntfToken )
{
CTokenListWalker *pChildList;
Token *pChildToken;
Token *pArgToken;
int cArgs;
CString szSuper;
pChildList = new CTokenListWalker ( pIntfToken );
szSuper = pIntfToken->GetTagValue ( INTERFACE_SUPER );
while ( pChildToken = pChildList -> GetNext() )
{
CString szRetValArg;
CString szRetValType;
CTokenListWalker ArgListWalker ( pChildToken );
cArgs = 0;
// Loop thru all arguments.
while ( (pArgToken = ArgListWalker.GetNext()) != NULL &&
pArgToken -> GetType () == TYPE_METHOD_ARG )
{
// Looking for a return value.
if ( pArgToken -> IsSet ( METHODARG_RETURNVALUE ) )
{
// If a return value exist then get the argument name.
szRetValArg = pArgToken -> GetTagValue (
pArgToken -> IsSet ( METHODARG_ARGNAME ) ?
METHODARG_ARGNAME : METHODARG_RETURNVALUE );
szRetValType = pArgToken -> GetTagValue ( METHODARG_TYPE );
}
else
{
cArgs++;
}
}
if ( strlen ( szRetValArg ) )
{
fprintf ( fpHTMFile, "<TR><TD>%s</TD><TD><I>object.</I><B>%s</B></TD>",
(LPCSTR)szRetValArg,
pChildToken -> GetTagValue ( METHOD_NAME ) );
}
else
{
fprintf ( fpHTMFile, "<TR><TD></TD><TD><I>object.</I><B>%s</B></TD>",
pChildToken -> GetTagValue ( METHOD_NAME ) );
}
int cArgIndex = 0;
ArgListWalker.Reset ( );
while ( ( pArgToken = ArgListWalker.GetNext ( ) ) != NULL &&
pArgToken -> GetType () == TYPE_METHOD_ARG )
{
if ( ! pArgToken -> IsSet ( METHODARG_RETURNVALUE ) )
{
if (cArgIndex == 0)
{
switch (cArgs)
{
case 0:
fprintf ( fpHTMFile, "<TD></TD><TD></TD><TD></TD><TD></TD><TD></TD> <!-- 1 -->" );
fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
(LPCSTR)szRetValType );
fprintf ( fpHTMFile, "</TR>\n" );
break;
default:
GenerateInterfaceArg( pArgToken );
fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
(LPCSTR)szRetValType );
fprintf ( fpHTMFile, "</TR>\n" );
break;
}
}
else
{
if (cArgIndex > 1)
{
fprintf ( fpHTMFile, "</TR> <!-- Hello -->\n" );
}
fprintf ( fpHTMFile, "<TR><TD></TD><TD></TD>" );
GenerateInterfaceArg( pArgToken );
}
cArgIndex++;
}
}
if ( cArgIndex == 0 )
{
fprintf ( fpHTMFile, "<TD></TD><TD></TD><TD></TD><TD></TD><TD></TD> <!-- 2 -->" );
fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
(LPCSTR)szRetValType );
fprintf ( fpHTMFile, "</TR>\n" );
}
else if ( cArgIndex > 1 )
{
fprintf ( fpHTMFile, "</TR> <!-- 3 -->\n" );
}
fprintf ( fpHTMFile, "<TR></TR>" );
}
delete pChildList;
}
void CPDLParser::GenerateEventMethodHTM ( Token *pIntfToken )
{
CTokenListWalker *pChildList;
Token *pChildToken;
Token *pArgToken;
int cArgs;
CString szSuper;
pChildList = new CTokenListWalker ( pIntfToken );
szSuper = pIntfToken->GetTagValue ( INTERFACE_SUPER );
while ( pChildToken = pChildList -> GetNext() )
{
CString szRetValArg;
CString szRetValType;
CTokenListWalker ArgListWalker ( pChildToken );
cArgs = 0;
// Loop thru all arguments.
while ( (pArgToken = ArgListWalker.GetNext()) != NULL &&
pArgToken -> GetType () == TYPE_METHOD_ARG )
{
// Looking for a return value.
if ( pArgToken -> IsSet ( METHODARG_RETURNVALUE ) )
{
// If a return value exist then get the argument name.
szRetValArg = pArgToken -> GetTagValue (
pArgToken -> IsSet ( METHODARG_ARGNAME ) ?
METHODARG_ARGNAME : METHODARG_RETURNVALUE );
szRetValType = pArgToken -> GetTagValue ( METHODARG_TYPE );
}
else
{
cArgs++;
}
}
if ( strlen ( szRetValArg ) )
{
fprintf ( fpHTMFile, "<TR><TD>%s</TD><TD><I>object.</I><B>%s</B></TD>",
(LPCSTR)szRetValArg,
pChildToken -> GetTagValue ( METHOD_NAME ) );
}
else
{
fprintf ( fpHTMFile, "<TR><TD></TD><TD><I>object.</I><B>%s</B></TD>",
pChildToken -> GetTagValue ( METHOD_NAME ) );
}
fprintf ( fpHTMFile, "<TD>%s</TD><TD>%s</TD><TD>%s</TD>",
pChildToken->IsSet(METHOD_DISPID) ? pChildToken->GetTagValue ( METHOD_DISPID ) : "",
pChildToken->IsSet(METHOD_CANCELABLE) ? "Y" : "N",
pChildToken->IsSet(METHOD_BUBBLING) ? "Y" : "N" );
int cArgIndex = 0;
ArgListWalker.Reset ( );
while ( ( pArgToken = ArgListWalker.GetNext ( ) ) != NULL &&
pArgToken -> GetType () == TYPE_METHOD_ARG )
{
if ( ! pArgToken -> IsSet ( METHODARG_RETURNVALUE ) )
{
if (cArgIndex == 0)
{
switch (cArgs)
{
case 0:
fprintf ( fpHTMFile, "<TD></TD><TD></TD><TD></TD><TD></TD><TD></TD> <!-- 1 -->" );
fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
(LPCSTR)szRetValType );
fprintf ( fpHTMFile, "</TR>\n" );
break;
default:
GenerateInterfaceArg( pArgToken );
fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
(LPCSTR)szRetValType );
fprintf ( fpHTMFile, "</TR>\n" );
break;
}
}
else
{
if (cArgIndex > 1)
{
fprintf ( fpHTMFile, "</TR> <!-- Hello -->\n" );
}
fprintf ( fpHTMFile, "<TR><TD></TD><TD></TD><TD></TD><TD></TD><TD></TD>" );
GenerateInterfaceArg( pArgToken );
}
cArgIndex++;
}
}
if ( cArgIndex == 0 )
{
fprintf ( fpHTMFile, "<TD></TD><TD></TD><TD></TD><TD></TD><TD></TD> <!-- 2 -->" );
fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
(LPCSTR)szRetValType );
fprintf ( fpHTMFile, "</TR>\n" );
}
else if ( cArgIndex > 1 )
{
fprintf ( fpHTMFile, "</TR> <!-- 3 -->\n" );
}
fprintf ( fpHTMFile, "<TR></TR>" );
}
delete pChildList;
}
void CPDLParser::GenerateEnumHTM ( Token *pClassToken, char *pEnumPrefix )
{
CTokenListWalker ChildList ( pClassToken );
Token *pChildToken;
CString szStringValue;
while ( pChildToken = ChildList.GetNext() )
{
if ( pChildToken -> GetType() == TYPE_EVAL )
{
fprintf ( fpHTMFile, "<TR>\n<TD>%s%s</TD><TD ALIGN=\"Center\">\"%s\"</TD>",
pEnumPrefix,
pChildToken -> GetTagValue ( EVAL_NAME ),
pChildToken -> IsSet ( EVAL_STRING ) ?
pChildToken -> GetTagValue ( EVAL_STRING ) :
pChildToken -> GetTagValue ( EVAL_NAME ) );
fprintf ( fpHTMFile, "</TR>\n");
}
}
}
void CPDLParser::GeneratePropertiesHTM ( Token *pIntfToken, BOOL fAttributes )
{
CTokenListWalker *pChildList;
Token *pChildToken;
CString szSuper;
CTokenListWalker *ptlw = NULL;
pChildList = new CTokenListWalker ( pIntfToken );
szSuper = pIntfToken->GetTagValue ( INTERFACE_SUPER );
do
{
while ( pChildToken = pChildList->GetNext() )
{
// Attributes are only properties which are not abstract and the
// ppflags is not PROPPARAM_NOTHTML.
if ( pChildToken -> GetType () == TYPE_PROPERTY &&
fAttributes == (
!pChildToken -> IsSet ( PROPERTY_ABSTRACT ) &&
pChildToken -> IsSet ( PROPERTY_NOPERSIST ) ) )
{
if (fAttributes)
{
fprintf ( fpHTMFile, "<TR><TD>%s</TD><TD>%s</TD><TD>%s</TD>",
pChildToken -> GetTagValue (
pChildToken -> IsSet ( PROPERTY_SZATTRIBUTE ) ?
PROPERTY_SZATTRIBUTE : PROPERTY_NAME ),
pChildToken -> GetTagValue ( PROPERTY_NAME ),
pChildToken -> GetTagValue ( PROPERTY_ATYPE ) );
}
else
{
fprintf ( fpHTMFile, "<TR><TD>%s</TD><TD>%s</TD>",
pChildToken -> GetTagValue ( PROPERTY_NAME ),
pChildToken -> GetTagValue ( PROPERTY_ATYPE ) );
}
fprintf ( fpHTMFile, "<TD>%s</TD>",
pChildToken -> IsSet ( PROPERTY_NOTPRESENTDEFAULT ) ?
pChildToken -> GetTagValue ( PROPERTY_NOTPRESENTDEFAULT ) :
"" );
fprintf ( fpHTMFile, "<TD>%s</TD>",
pChildToken -> IsSet ( PROPERTY_MIN ) ?
pChildToken -> GetTagValue ( PROPERTY_MIN ) :
"" );
fprintf ( fpHTMFile, "<TD>%s</TD>",
pChildToken -> IsSet ( PROPERTY_MAX ) ?
pChildToken -> GetTagValue ( PROPERTY_MAX ) :
"" );
if ( pChildToken -> IsSet ( PROPERTY_SET ) &&
pChildToken -> IsSet ( PROPERTY_GET ) )
{
fprintf ( fpHTMFile, "<TD>R/W</TD>" );
}
else if ( pChildToken -> IsSet ( PROPERTY_GET ) )
{
fprintf ( fpHTMFile, "<TD>R/O</TD>" );
}
else
{
fprintf ( fpHTMFile, "<TD>W/O</TD>" );
}
fprintf ( fpHTMFile,
pChildToken -> IsSet ( PROPERTY_SETDESIGNMODE ) ?
"<TD>R/W</TD>" : "<TD>R/O</TD>" );
fprintf ( fpHTMFile, "</TR>\n" );
}
}
// Get inherited interface.
if ( strlen ( szSuper ) )
{
if (ptlw == NULL)
{
ptlw = new CTokenListWalker ( pRuntimeList, _pszPDLFileName );
}
else
{
ptlw->Reset();
}
TryAgain:
pIntfToken = ptlw->GetNext ( TYPE_INTERFACE, szSuper );
if (pIntfToken)
{
szSuper = pIntfToken->GetTagValue ( INTERFACE_SUPER );
delete pChildList;
pChildList = new CTokenListWalker ( pIntfToken );
}
else
{
if ( !ptlw->IsGenericWalker ( ) )
{
delete ptlw;
ptlw = new CTokenListWalker ( pRuntimeList );
goto TryAgain;
}
}
}
else
{
break;
}
} while (pIntfToken);
delete pChildList;
delete ptlw;
}
#define GET_TAG_VALUE(pToken, value) (pToken->IsSet(value) ? pToken->GetTagValue(value) : "")
void CPDLParser::GenerateInterfacePropertiesHTM ( Token *pIntfToken )
{
CTokenListWalker *pChildList;
Token *pChildToken;
CString szSuper;
pChildList = new CTokenListWalker ( pIntfToken );
szSuper = pIntfToken->GetTagValue ( INTERFACE_SUPER );
while ( pChildToken = pChildList->GetNext() )
{
if ( pChildToken -> GetType () == TYPE_PROPERTY )
{
fprintf ( fpHTMFile, "<TR>" );
fprintf ( fpHTMFile, "<TD>%s</TD>", GET_TAG_VALUE(pChildToken, PROPERTY_NAME) );
fprintf ( fpHTMFile, "<TD>%s</TD>", GET_TAG_VALUE(pChildToken, PROPERTY_ATYPE) );
fprintf ( fpHTMFile, "<TD>%s</TD>", GET_TAG_VALUE(pChildToken, PROPERTY_DISPID) );
fprintf ( fpHTMFile, "<TD>%s</TD>", pChildToken->IsSet(PROPERTY_GET) ? "Y" : "N" );
fprintf ( fpHTMFile, "<TD>%s</TD>", pChildToken->IsSet(PROPERTY_SET) ? "Y" : "N" );
fprintf ( fpHTMFile, "<TD>%s</TD>", pChildToken->IsSet(PROPERTY_SETDESIGNMODE) ? "Y" : "N" );
fprintf ( fpHTMFile, "<TD>%s</TD>", pChildToken->IsSet(PROPERTY_NOTPRESENTDEFAULT) ? pChildToken->GetTagValue(PROPERTY_NOTPRESENTDEFAULT) : "" );
fprintf ( fpHTMFile, "<TD>%s</TD>", pChildToken->IsSet(PROPERTY_MIN) ? pChildToken->GetTagValue(PROPERTY_MIN) : "" );
fprintf ( fpHTMFile, "<TD>%s</TD>", pChildToken->IsSet(PROPERTY_MAX) ? pChildToken->GetTagValue(PROPERTY_MAX) : "" );
fprintf ( fpHTMFile, "</TR>\n" );
}
}
delete pChildList;
}
#undef GET_TAG_VALUE
Token* CPDLParser::FindInterface (CString szInterfaceMatch)
{
CTokenListWalker WholeTree ( pRuntimeList );
Token *pInterfaceToken;
WholeTree.Reset();
while ( pInterfaceToken = WholeTree.GetNext ( TYPE_INTERFACE ) )
{
CString szInterface;
if ( !pInterfaceToken -> IsSet ( INTERFACE_ABSTRACT ) &&
pInterfaceToken -> IsSet ( INTERFACE_GUID ) )
{
szInterface = pInterfaceToken -> GetTagValue ( INTERFACE_NAME );
if (szInterface == szInterfaceMatch)
{
return pInterfaceToken;
}
}
}
return NULL;
}
// Only interfaces defined in this file.
Token* CPDLParser::FindInterfaceLocally (CString szInterfaceMatch)
{
CTokenListWalker TokenList ( pRuntimeList, _pszPDLFileName );
Token *pInterfaceToken;
TokenList.Reset();
while ( pInterfaceToken = TokenList.GetNext ( TYPE_INTERFACE ) )
{
CString szInterface;
if ( !pInterfaceToken -> IsSet ( INTERFACE_ABSTRACT ) &&
pInterfaceToken -> IsSet ( INTERFACE_GUID ) )
{
szInterface = pInterfaceToken -> GetTagValue ( INTERFACE_NAME );
if (szInterface == szInterfaceMatch)
{
return pInterfaceToken;
}
}
}
return NULL;
}
BOOL CPDLParser::IsPrimaryInterface(CString szInterface)
{
CTokenListWalker TokenList ( pRuntimeList, _pszPDLFileName );
Token *pClassToken;
TokenList.Reset();
while ( pClassToken = TokenList.GetNext ( TYPE_CLASS ) )
{
if (!_stricmp((LPSTR)pClassToken->GetTagValue(CLASS_INTERFACE),
szInterface))
return TRUE;
}
return FALSE;
}
Token* CPDLParser::FindClass (CString szClassMatch)
{
CTokenListWalker WholeTree ( pRuntimeList );
Token *pClassToken;
WholeTree.Reset();
while ( pClassToken = WholeTree.GetNext ( TYPE_CLASS ) )
{
CString szClass;
szClass = pClassToken -> GetTagValue ( CLASS_NAME );
if (szClass == szClassMatch)
{
return pClassToken;
}
}
return NULL;
}
Token * CPDLParser::IsSuperInterface( CString szSuper, Token * pInterface )
{
Token *pInterfaceToken;
CString szInterface;
if(!pInterface)
return NULL;
szInterface = pInterface->GetTagValue(INTERFACE_NAME);
pInterfaceToken = pInterface;
while ( pInterfaceToken )
{
if (szSuper == szInterface)
return pInterfaceToken;
szInterface = pInterfaceToken->GetTagValue(INTERFACE_SUPER);
pInterfaceToken = FindInterface(szInterface);
}
return NULL;
}
Token *
CPDLParser::FindMatchingEntryWOPropDesc(Token *pClass, Token *pToFindToken, BOOL fNameMatchOnly)
{
CTokenListWalker ChildWalker(pClass);
Token *pChildToken;
CString szInterface;
Token *pInterfToken;
Token *pFuncToken = NULL;
while (pChildToken = ChildWalker.GetNext())
{
if (pChildToken->GetType() == TYPE_IMPLEMENTS)
{
szInterface = pChildToken->GetTagValue(IMPLEMENTS_NAME);
pInterfToken = FindInterface(szInterface);
if (pInterfToken)
{
pFuncToken = FindMethodInInterfaceWOPropDesc(pInterfToken, pToFindToken, fNameMatchOnly);
if (pFuncToken)
break; // Found a match...
}
}
}
return pFuncToken;
}
Token*
CPDLParser::FindMethodInInterfaceWOPropDesc(Token *pInterface, Token *pToFindToken, BOOL fNameMatchOnly)
{
CTokenListWalker ChildList(pInterface);
Token *pChildToken = NULL;
while (pChildToken = ChildList.GetNext())
{
if (pChildToken->GetType() == pToFindToken->GetType())
{
if (pChildToken->GetType() == TYPE_METHOD && !pChildToken->IsSet(METHOD_NOPROPDESC))
{
CString szMethodName;
if (pToFindToken->IsSet(METHOD_NOPROPDESC) &&
pToFindToken->IsSet(METHOD_SZINTERFACEEXPOSE))
{
szMethodName = pToFindToken->GetTagValue(METHOD_SZINTERFACEEXPOSE);
}
else
{
szMethodName = pToFindToken->GetTagValue(METHOD_NAME);
}
if (!strcmp((LPCSTR)szMethodName,
(LPCSTR)pChildToken->GetTagValue(METHOD_NAME)))
{
CString szTypesSig;
CString szArgsType;
CString szFindTypesSig;
CString szFindArgsType;
BOOL fIgnore;
int cIgnore;
// If we only need a name match then we're done.
if (fNameMatchOnly)
break;
if (!BuildMethodSignature(pChildToken,
szTypesSig,
szArgsType,
fIgnore,
fIgnore,
cIgnore,
cIgnore))
return NULL;
if (!BuildMethodSignature(pToFindToken,
szFindTypesSig,
szFindArgsType,
fIgnore,
fIgnore,
cIgnore,
cIgnore))
return NULL;
// Exact signature match then use it.
if (!strcmp(szTypesSig, szFindTypesSig) &&
!strcmp(szArgsType, szFindArgsType))
break;
}
}
else if (pChildToken->GetType() == TYPE_PROPERTY && !pChildToken->IsSet(PROPERTY_NOPROPDESC))
{
CString szPropertyName;
if (pToFindToken->IsSet(PROPERTY_NOPROPDESC) &&
pToFindToken->IsSet(PROPERTY_SZINTERFACEEXPOSE))
{
szPropertyName = pToFindToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE);
}
else
{
szPropertyName = pToFindToken->GetTagValue(PROPERTY_NAME);
}
if (!strcmp((LPCSTR)szPropertyName,
(LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME)))
{
// If we only need a name match then we're done.
if (fNameMatchOnly)
break;
// If both are properties and the types are similar or an
// enum then the signature is the same we found a match.
if ((pChildToken->IsSet(PROPERTY_GETSETMETHODS) == pToFindToken->IsSet(PROPERTY_GETSETMETHODS)) &&
(pChildToken->IsSet(PROPERTY_MEMBER) == pToFindToken->IsSet(PROPERTY_MEMBER)) &&
(pChildToken->IsSet(PROPERTY_GET) == pToFindToken->IsSet(PROPERTY_GET)) &&
(pChildToken->IsSet(PROPERTY_SET) == pToFindToken->IsSet(PROPERTY_SET)))
{
if (!strcmp((LPCSTR)pChildToken->GetTagValue(PROPERTY_ATYPE),
(LPCSTR)pToFindToken->GetTagValue(PROPERTY_ATYPE)))
break;
if (FindEnum(pChildToken) && FindEnum(pToFindToken))
break;
}
}
}
}
}
return pChildToken;
}