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
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, " [%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, " )</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> " );
|
|
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> </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;
|
|
}
|