Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

9190 lines
329 KiB

  1. extern BOOL gbWin16Mode;
  2. UINT CPDLParser::CountTags ( TokenDescriptor *tokdesc )
  3. {
  4. UINT uCount;
  5. TagDescriptor *pTagDescriptor;
  6. for ( uCount = 0, pTagDescriptor = tokdesc -> Tags ; pTagDescriptor -> szTag != NULL;
  7. uCount++, pTagDescriptor++ );
  8. return uCount;
  9. }
  10. CPDLParser::CPDLParser()
  11. {
  12. fpHComPlusFile = NULL;
  13. fpCComPlusFile = NULL;
  14. fpHDLFile = NULL;
  15. fpHeaderFile = NULL;
  16. fpIDLFile = NULL;
  17. fpLOGFile = NULL;
  18. fpHTMFile = NULL;
  19. fpHTMIndexFile = NULL;
  20. fpDISPIDFile = NULL;
  21. fpMaxLenFile = NULL;
  22. pRuntimeList = new CTokenList;
  23. pDynamicTypeList = new CTokenList;
  24. pDynamicEventTypeList = new CTokenList;
  25. Init();
  26. }
  27. void
  28. CPDLParser::SplitTag ( char *pStr, int nLen, char **pTag, int *pnTagLen,
  29. char **pValue, int *pnValueLen )
  30. {
  31. *pTag = pStr;
  32. for ( *pnTagLen = 0 ; *pnTagLen < nLen ; pStr++, (*pnTagLen)++ )
  33. {
  34. if ( *pStr == ':' )
  35. {
  36. *pValue = pStr + 1;
  37. *pnValueLen = nLen - *pnTagLen -1;
  38. return;
  39. }
  40. }
  41. *pnValueLen = 0;
  42. }
  43. BOOL
  44. CPDLParser::LookupToken ( LPCSTR pTokenName, int nTokenLen,
  45. TokenDescriptor **ppTokenDescriptor, DESCRIPTOR_TYPE *pnTokenDes )
  46. {
  47. INT i;
  48. for ( i = 0 ;
  49. i < NUM_DESCRIPTOR_TYPES ; i++ )
  50. {
  51. if (strlen(AllDescriptors[i]->szTokenName) == (UINT)nTokenLen &&
  52. !_strnicmp(AllDescriptors[i]->szTokenName, pTokenName, nTokenLen))
  53. {
  54. *ppTokenDescriptor = AllDescriptors [ i ];
  55. *pnTokenDes = (DESCRIPTOR_TYPE)i;
  56. return TRUE;
  57. }
  58. }
  59. return FALSE;
  60. }
  61. BOOL CPDLParser::GetElem ( char **pStr,
  62. char **pElem,
  63. int *pnLen,
  64. BOOL fBreakOnOpenParenthesis, /* = FALSE */
  65. BOOL fBreakOnCloseParenthesis, /* = FALSE */
  66. BOOL fBreakOnCommas /* = FALSE */ )
  67. {
  68. *pnLen = 0;
  69. while ( isspace ( **pStr ) )
  70. {
  71. (*pStr)++;
  72. }
  73. *pElem = *pStr;
  74. if (( fBreakOnOpenParenthesis && **pStr == ')' ) ||
  75. ( fBreakOnCloseParenthesis && **pStr == '(' ) ||
  76. (fBreakOnCommas && **pStr == ',' ))
  77. {
  78. (*pnLen)++;
  79. (*pStr)++;
  80. goto Cleanup;
  81. }
  82. while ( **pStr && !isspace ( **pStr ))
  83. {
  84. if (( fBreakOnOpenParenthesis && **pStr == ')' ) ||
  85. ( fBreakOnCloseParenthesis && **pStr == '(' ) ||
  86. (fBreakOnCommas && **pStr == ',' ))
  87. {
  88. // Break but leave the pStr pointing at the bracket - we'll pick it up in the
  89. // next call
  90. break;
  91. }
  92. // Convert curly braces to parens
  93. if (**pStr == '{')
  94. **pStr = '(';
  95. else if (**pStr == '}')
  96. **pStr = ')';
  97. (*pnLen)++;
  98. (*pStr)++;
  99. }
  100. Cleanup:
  101. return *pnLen == 0 ? FALSE : TRUE;
  102. }
  103. BOOL CPDLParser::ParseInputFile ( BOOL fDebugging )
  104. {
  105. BOOL fReturn = TRUE;
  106. DESCRIPTOR_TYPE nThisDescriptor;
  107. char szLineBuffer [ MAX_LINE_LEN+1 ];
  108. char szErrorText [ MAX_LINE_LEN+1 ];
  109. char *pStr = szLineBuffer;
  110. char *pElem; int nElemLen;
  111. TokenDescriptor *pThisDescriptor;
  112. Token *pNewToken;
  113. Token *pParentToken = NULL;
  114. BOOL fGotParentToken = FALSE;
  115. CString szType;
  116. fprintf ( fpLOGFile, "Parsing input file\n" );
  117. for(;;)
  118. {
  119. if ( !GetStdInLine ( szLineBuffer, sizeof ( szLineBuffer ) ) )
  120. break;
  121. pStr = szLineBuffer;
  122. fprintf ( fpLOGFile, "Read Line:%s\n", szLineBuffer );
  123. // Get the type e..g. enum, eval etc.
  124. if ( !GetElem ( &pStr, &pElem, &nElemLen ) )
  125. {
  126. // Couldn't get the name
  127. fprintf ( fpLOGFile, "Skipping\n" );
  128. continue;
  129. }
  130. if ( !LookupToken ( pElem, nElemLen, &pThisDescriptor, &nThisDescriptor ) )
  131. {
  132. fprintf ( fpLOGFile, "Unknown token\n" );
  133. continue;
  134. }
  135. fprintf ( fpLOGFile, "Processing a %s declaration\n",
  136. (LPCSTR)AllDescriptors [ nThisDescriptor ] -> szTokenName );
  137. // If it's a child token and we haven't got a parent
  138. if ( !pThisDescriptor->fIsParentToken &&
  139. !fGotParentToken )
  140. {
  141. ReportError ( "Child Token Without Parent\n" );
  142. goto error;
  143. }
  144. if ( pThisDescriptor->fIsParentToken )
  145. {
  146. fGotParentToken = TRUE;
  147. }
  148. INT nTag;
  149. char *pTag; char *pValue;
  150. int nTagLen; int nValueLen;
  151. BOOL fVarArg = FALSE;
  152. if ( nThisDescriptor == TYPE_METHOD )
  153. {
  154. // Look for optional vararg first
  155. if ( !GetElem ( &pStr, &pElem, &nElemLen ) )
  156. {
  157. // Couldn't get the return type
  158. continue;
  159. }
  160. if ( ! ( pNewToken = pParentToken -> AddChildToken ( nThisDescriptor ) ) )
  161. {
  162. ReportError ( "Memory Allocation Error\n" );
  163. goto error;
  164. }
  165. if ( !pNewToken->TagValues.AddTag ( METHOD_RETURNTYPE, pElem, nElemLen ) )
  166. {
  167. ReportError ( "Memory Allocation Error\n" );
  168. goto error;
  169. }
  170. // Name is next
  171. if ( !GetElem ( &pStr, &pElem, &nElemLen ) )
  172. {
  173. // Couldn't get the name
  174. continue;
  175. }
  176. if ( !pNewToken->TagValues.AddTag ( METHOD_NAME, pElem, nElemLen ) )
  177. {
  178. ReportError ( "Memory Allocation Error\n" );
  179. goto error;
  180. }
  181. // Methods need special handling due to the parameter list
  182. // Put all tokens before the "(" in the TagValues
  183. // Treat each arg in the param list as a unique token and add
  184. // to the pArgList for this token
  185. // Put all the tokens after the ")" in the TagValues
  186. // We allow either a comma-seperated arg list, but if we
  187. // don't get commas we break the arg intelligently
  188. //
  189. UINT bInParams = FALSE;
  190. BOOL bCreatedArgToken = FALSE;
  191. Token *pCurrentToken;
  192. TokenDescriptor *pDescriptor = pThisDescriptor;
  193. pCurrentToken = pNewToken;
  194. fVarArg = FALSE;
  195. // Set the fBreakOnParenthesis Flag to make parenthis stop GetElem
  196. while ( GetElem ( &pStr, &pElem, &nElemLen, TRUE, TRUE, TRUE ) )
  197. {
  198. if ( nElemLen == 1 && *pElem == '(' )
  199. {
  200. if ( bInParams )
  201. {
  202. sprintf ( szErrorText, "Syntax Error %s On %s\n", pStr, szLineBuffer );
  203. ReportError ( szErrorText );
  204. goto error;
  205. }
  206. bInParams = TRUE;
  207. // Switch to method arg descriptor
  208. pDescriptor = &MethodArgDescriptor;
  209. }
  210. else if ( nElemLen == 1 && *pElem == ')' )
  211. {
  212. if ( !bInParams )
  213. {
  214. sprintf ( szErrorText, "Syntax Error %s On %s\n", pStr, szLineBuffer );
  215. ReportError ( szErrorText );
  216. goto error;
  217. }
  218. bInParams = FALSE;
  219. // Switch back to method descriptor
  220. pDescriptor = pThisDescriptor;
  221. pCurrentToken = pNewToken;
  222. }
  223. else if ( nElemLen == 1 && *pElem == ',' )
  224. {
  225. // Reset flag so new arg token gets created for next arg
  226. bCreatedArgToken = FALSE;
  227. }
  228. else
  229. {
  230. // Split out the prefix:value
  231. SplitTag ( pElem, nElemLen, &pTag, &nTagLen,
  232. &pValue, &nValueLen );
  233. // Match the tag
  234. if ( !pDescriptor->LookupTagName ( pTag, nTagLen, &nTag ) )
  235. {
  236. pTag [ nTagLen ] = '\0';
  237. sprintf ( szErrorText, "Unknown tag: %s On %s\n", pTag, szLineBuffer );
  238. ReportError ( szErrorText );
  239. goto error;
  240. }
  241. // If we've already got an entry for this tag, and we've seen
  242. // at least the arg tag, start a new arg
  243. if ( bInParams && pCurrentToken -> IsSet ( METHODARG_ARGNAME ) &&
  244. ( nTag == METHODARG_IN || nTag == METHODARG_OUT ) &&
  245. ( pCurrentToken -> IsSet ( METHODARG_IN ) ||
  246. pCurrentToken -> IsSet ( METHODARG_IN ) ) )
  247. {
  248. // Start a new arg
  249. bCreatedArgToken = FALSE;
  250. }
  251. if ( bInParams && bCreatedArgToken == FALSE )
  252. {
  253. // Create the arg list if needed
  254. pCurrentToken = pNewToken -> AddChildToken ( TYPE_METHOD_ARG );
  255. if ( pCurrentToken == NULL )
  256. {
  257. ReportError ( "Memory allocation error\n" );
  258. goto error;
  259. }
  260. bCreatedArgToken = TRUE;
  261. }
  262. // Add the tag either to the main method token array or to the current
  263. // arg 's array
  264. if ( !pCurrentToken->TagValues.AddTag ( nTag, pValue, nValueLen ) )
  265. {
  266. ReportError ( "Memory allocation error\n" );
  267. goto error;
  268. }
  269. // Last argument a SAFEARRAY, if so then vararg
  270. fVarArg = (strncmp(pValue, "SAFEARRAY(VARIANT)", 18) == 0);
  271. }
  272. // method is a vararg because last parameter is a safearray.
  273. if ( fVarArg && !pNewToken->TagValues.AddTag ( METHOD_VARARG, "vararg", 6 ) )
  274. {
  275. ReportError ( "Memory allocation error\n" );
  276. goto error;
  277. }
  278. }
  279. }
  280. else if ( nThisDescriptor == TYPE_REFPROP || nThisDescriptor == TYPE_REFMETHOD )
  281. {
  282. // Now get the Class::Name & split it out
  283. if ( !GetElem ( &pStr, &pElem, &nElemLen ) )
  284. {
  285. // Couldn't get the name
  286. continue;
  287. }
  288. // Split out the prefix:value
  289. SplitTag ( pElem, nElemLen, &pTag, &nTagLen,
  290. &pValue, &nValueLen );
  291. pNewToken = pParentToken -> AddChildToken ( nThisDescriptor );
  292. if ( pNewToken == NULL )
  293. {
  294. ReportError ( "Memory Allocation Error\n" );
  295. goto error;
  296. }
  297. if ( !pNewToken->TagValues.AddTag (
  298. (nThisDescriptor == TYPE_REFPROP) ? (INT)REFPROP_CLASSNAME : (INT)REFMETHOD_CLASSNAME,
  299. pTag, nTagLen ) )
  300. {
  301. ReportError ( "Memory Allocation Error\n" );
  302. goto error;
  303. }
  304. if ( !pNewToken->TagValues.AddTag (
  305. nThisDescriptor == TYPE_REFPROP ? (INT)REFPROP_PROPERTYNAME : (INT)REFMETHOD_METHODNAME,
  306. pValue, nValueLen ) )
  307. {
  308. ReportError ( "Memory Allocation Error\n" );
  309. goto error;
  310. }
  311. }
  312. else
  313. {
  314. // Now get the name
  315. if ( !GetElem ( &pStr, &pElem, &nElemLen ) )
  316. {
  317. // Couldn't get the name
  318. continue;
  319. }
  320. // If it's a child token, add it to the runtime list, else add it as a child
  321. // of the current parent
  322. if ( pThisDescriptor->fIsParentToken )
  323. {
  324. pNewToken = pRuntimeList -> AddNewToken ( nThisDescriptor );
  325. pParentToken = pNewToken;
  326. }
  327. else
  328. {
  329. pNewToken = pParentToken -> AddChildToken ( nThisDescriptor );
  330. }
  331. if ( pNewToken == NULL )
  332. {
  333. ReportError ( "Memory Allocation Error\n" );
  334. goto error;
  335. }
  336. // First tag is always the name
  337. if ( !pNewToken->TagValues.AddTag ( NAME_TAG, pElem, nElemLen ) )
  338. {
  339. ReportError ( "Memory Allocation Error\n" );
  340. goto error;
  341. }
  342. // Split out all the token:value pairs
  343. while ( GetElem ( &pStr, &pElem, &nElemLen ) )
  344. {
  345. // Split out the prefix:value
  346. SplitTag ( pElem, nElemLen, &pTag, &nTagLen,
  347. &pValue, &nValueLen );
  348. // Match the tag
  349. if ( !pThisDescriptor->LookupTagName ( pTag, nTagLen, &nTag ) )
  350. {
  351. pTag [ nTagLen ] = '\0';
  352. sprintf ( szErrorText, "Unknown tag: %s On %s\n", pTag, szLineBuffer );
  353. ReportError ( szErrorText );
  354. goto error;
  355. }
  356. if ( !pNewToken->TagValues.AddTag ( nTag, pValue, nValueLen ) )
  357. {
  358. ReportError ( "Memory Allocation Error\n" );
  359. goto error;
  360. }
  361. }
  362. }
  363. // Perform any cleanup
  364. switch ( nThisDescriptor )
  365. {
  366. case TYPE_EVAL:
  367. // For enums we calculate and store in the token the enum mask
  368. // We also number the enum values sequentialy
  369. pNewToken -> CalculateEnumMask ( pParentToken );
  370. break;
  371. case TYPE_ENUM:
  372. // Add data types to the dynamic type array
  373. szType = pNewToken -> GetTagValue ( ENUM_NAME );
  374. AddType ( szType, "Enum" );
  375. AddEventType ( szType, "VTS_I4" );
  376. szType += "*";
  377. AddEventType ( szType, "VTS_PI4" );
  378. break;
  379. case TYPE_CLASS:
  380. case TYPE_INTERFACE:
  381. case TYPE_EVENT:
  382. szType = pNewToken -> GetTagValue ( NAME_TAG );
  383. szType += "*";
  384. AddType ( szType, "object" );
  385. AddEventType ( szType, "VTS_DISPATCH" );
  386. szType += "*";
  387. AddType ( szType, "object" );
  388. AddEventType ( szType, "VTS_DISPATCH" );
  389. break;
  390. }
  391. }
  392. // Add an IUnknown to make implicit ref's match up
  393. pNewToken = pRuntimeList -> AddNewToken ( TYPE_INTERFACE );
  394. pNewToken->TagValues.AddTag ( INTERFACE_NAME, "IUnknown", -1 );
  395. // Add an IDispatch to make implicit ref's match up
  396. pNewToken = pRuntimeList -> AddNewToken ( TYPE_INTERFACE );
  397. pNewToken->TagValues.AddTag ( INTERFACE_NAME, "IDispatch", -1 );
  398. pNewToken = pRuntimeList -> AddNewToken ( TYPE_EVENT );
  399. pNewToken->TagValues.AddTag ( EVENT_NAME, "IDispatch", -1 );
  400. // Patch up the refprops & refmethods
  401. if ( !PatchInterfaceRefTypes() )
  402. {
  403. goto error;
  404. }
  405. // Patch Properties that are of object type
  406. if ( !PatchPropertyTypes() )
  407. {
  408. goto error;
  409. }
  410. if ( !PatchInterfaces() )
  411. {
  412. goto error;
  413. }
  414. goto cleanup;
  415. error:
  416. fReturn = FALSE;
  417. cleanup:
  418. return fReturn;
  419. }
  420. BOOL CPDLParser::PatchInterfaceRefTypes ( void )
  421. {
  422. CTokenListWalker WholeTree ( pRuntimeList );
  423. Token *pChildToken;
  424. Token *pInterfaceToken;
  425. CString szClassName;
  426. // For each RefProp or Refmethod, we replace the arg list with a copy of the referenced property/method
  427. // and change the type of the ref'd item appropriatly
  428. while ( pInterfaceToken = WholeTree.GetNext( TYPE_INTERFACE ) )
  429. {
  430. CTokenListWalker ChildList ( pInterfaceToken );
  431. while ( pChildToken = ChildList.GetNext() )
  432. {
  433. if ( pChildToken -> GetType() == TYPE_REFPROP )
  434. {
  435. szClassName = pChildToken -> GetTagValue ( REFPROP_CLASSNAME );
  436. if ( !CloneToken ( pChildToken, TYPE_PROPERTY,
  437. REFPROP_CLASSNAME, REFPROP_PROPERTYNAME ) )
  438. {
  439. char szErrorText [ MAX_LINE_LEN+1 ];
  440. sprintf ( szErrorText, "Interface %s Invalid RefProp %s:%s\n" ,
  441. pInterfaceToken -> GetTagValue ( INTERFACE_NAME ),
  442. pChildToken -> GetTagValue ( REFPROP_CLASSNAME ),
  443. pChildToken -> GetTagValue ( REFPROP_PROPERTYNAME ) );
  444. ReportError ( szErrorText );
  445. return FALSE;
  446. }
  447. // Remember the class that was refprop'd.
  448. pChildToken -> AddTag ( PROPERTY_REFDTOCLASS, (LPCSTR)szClassName );
  449. }
  450. else if ( pChildToken -> GetType() == TYPE_REFMETHOD )
  451. {
  452. szClassName = pChildToken -> GetTagValue ( REFMETHOD_CLASSNAME );
  453. if ( !CloneToken ( pChildToken, TYPE_METHOD,
  454. REFMETHOD_CLASSNAME, REFMETHOD_METHODNAME ) )
  455. {
  456. char szErrorText [ MAX_LINE_LEN+1 ];
  457. sprintf ( szErrorText, "Interface %s Invalid RefMethod %s:%s\n" ,
  458. pInterfaceToken -> GetTagValue ( INTERFACE_NAME ),
  459. pChildToken -> GetTagValue ( REFMETHOD_CLASSNAME ),
  460. pChildToken -> GetTagValue ( REFMETHOD_METHODNAME ) );
  461. ReportError ( szErrorText );
  462. return FALSE;
  463. }
  464. // Remember the class that was refprop'd.
  465. pChildToken -> AddTag ( METHOD_REFDTOCLASS, (LPCSTR)szClassName );
  466. }
  467. }
  468. }
  469. return TRUE;
  470. }
  471. BOOL CPDLParser::CloneToken ( Token *pChildToken, DESCRIPTOR_TYPE Type, INT nClassName, INT nTagName )
  472. {
  473. CTokenListWalker SubTree ( pRuntimeList );
  474. Token *pRefdClassToken;
  475. Token *pRefdChild;
  476. pRefdClassToken = SubTree.GetNext( TYPE_CLASS, pChildToken -> GetTagValue ( nClassName ) );
  477. if ( pRefdClassToken == NULL )
  478. {
  479. // Couldn't find the refd class
  480. return FALSE;
  481. }
  482. // Found the refd class, find the refd property
  483. CTokenListWalker RefdChildList ( pRefdClassToken );
  484. pRefdChild = RefdChildList.GetNext ( Type,
  485. pChildToken -> GetTagValue ( nTagName ) );
  486. if ( pRefdChild == NULL )
  487. {
  488. // Couldn't find the refd property
  489. return FALSE;
  490. }
  491. else
  492. {
  493. pChildToken -> Clone ( pRefdChild );
  494. }
  495. return TRUE;
  496. }
  497. BOOL CPDLParser::GetTypeDetails ( char *szTypeName, CString& szHandler, CString &szFnPrefix,
  498. StorageType *pStorageType /* = NULL */ )
  499. {
  500. if ( !LookupType ( szTypeName, szHandler, szFnPrefix, pStorageType ) )
  501. return FALSE;
  502. return TRUE;
  503. }
  504. BOOL CPDLParser::IsSpecialProperty(Token *pClassToken)
  505. {
  506. CString szInterf;
  507. Token *pInterf;
  508. szInterf = pClassToken->GetTagValue(CLASS_INTERFACE);
  509. pInterf = FindInterface(szInterf);
  510. if (pInterf)
  511. return (PrimaryTearoff(pInterf) || pInterf->IsSet(INTERFACE_ABSTRACT));
  512. else
  513. return TRUE;
  514. }
  515. BOOL CPDLParser::GeneratePropMethodImplementation ( void )
  516. {
  517. Token *pClassToken;
  518. Token *pChildToken;
  519. CString szFnPrefix;
  520. CString szHandler;
  521. CString szOffsetOf;
  522. CString szAType;
  523. CString szHandlerArgs;
  524. char szErrorText [ MAX_LINE_LEN+1 ];
  525. // Only generate def's for this file
  526. CTokenListWalker TokenList ( pRuntimeList, _pszPDLFileName );
  527. // Generate propdescs for every property token in every class ( in this file )
  528. while ( pClassToken = TokenList.GetNext( TYPE_CLASS ) )
  529. {
  530. if (!IsSpecialProperty(pClassToken))
  531. {
  532. fprintf ( fpHDLFile, "\n// Property get/set method implementation for class %s\n", (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ) );
  533. fprintf ( fpHDLFile, "\n" );
  534. CTokenListWalker ChildList ( pClassToken );
  535. while ( pChildToken = ChildList.GetNext() )
  536. {
  537. if ( pChildToken->nType == TYPE_METHOD ||
  538. pChildToken->nType == TYPE_IMPLEMENTS ||
  539. pChildToken -> IsSet ( PROPERTY_ABSTRACT ) ||
  540. pChildToken -> IsSet ( PROPERTY_BASEIMPLEMENTATION ) )
  541. {
  542. continue;
  543. }
  544. // If propdesc for nameOnly then we wont need a handler for this property
  545. // another property that matches this will do the handling.
  546. if ( _stricmp(pChildToken->GetTagValue(PROPERTY_NOPROPDESC), "nameonly") == 0 )
  547. continue;
  548. if ( !GetTypeDetails ( pChildToken->GetTagValue ( PROPERTY_TYPE ),
  549. szHandler, szFnPrefix ) )
  550. {
  551. sprintf ( szErrorText ,"Invalid Type:%s in Class:%s Property:%s\n",
  552. (LPCSTR)pChildToken->GetTagValue ( PROPERTY_TYPE ),
  553. (LPCSTR)pClassToken->GetTagValue(CLASS_NAME),
  554. (LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ) );
  555. ReportError ( szErrorText );
  556. return FALSE;
  557. }
  558. if ( pChildToken -> IsSet ( PROPERTY_CAA ) )
  559. {
  560. szOffsetOf = "(GetAttrArray())";
  561. }
  562. else
  563. {
  564. szOffsetOf = "(this)";
  565. }
  566. szAType = pChildToken->GetTagValue ( PROPERTY_ATYPE );
  567. // Generate set implementation
  568. if ( pChildToken -> IsSet ( PROPERTY_SET ) )
  569. {
  570. szHandlerArgs = "HANDLEPROP_SET | HANDLEPROP_AUTOMATION | (PROPTYPE_VARIANT << 16)";
  571. GenerateMethodImp ( pClassToken, pChildToken, TRUE,
  572. szHandler, szHandlerArgs, szOffsetOf, szAType );
  573. }
  574. // Generate Get implementation
  575. if ( pChildToken -> IsSet ( PROPERTY_GET ) )
  576. {
  577. szHandlerArgs = "HANDLEPROP_AUTOMATION | (PROPTYPE_VARIANT << 16)";
  578. GenerateMethodImp ( pClassToken, pChildToken, FALSE,
  579. szHandler, szHandlerArgs, szOffsetOf, szAType );
  580. }
  581. }
  582. }
  583. fprintf ( fpHDLFile, "\n" );
  584. // Whip thru all tearoffs.
  585. Token *pLastTearoff = NULL;
  586. BOOL fMostDerivedOnly;
  587. while ((pLastTearoff = NextTearoff((LPCSTR)pClassToken->GetTagValue(CLASS_NAME), pLastTearoff)))
  588. {
  589. LPSTR szInterface = (LPSTR)pLastTearoff->GetTagValue(TEAROFF_INTERFACE);
  590. // If the tearoff is the primary interface of the coclass then we'll
  591. // not stack the derived interfaces but generate separate
  592. fMostDerivedOnly = (_stricmp(szInterface, (LPSTR)pClassToken->GetTagValue(CLASS_INTERFACE)) == 0 &&
  593. _stricmp(szInterface, "IHTMLDocument2"));
  594. if ( !GenerateTearoffTable(pClassToken, pLastTearoff, szInterface, fMostDerivedOnly))
  595. return FALSE;
  596. }
  597. }
  598. return TRUE;
  599. }
  600. BOOL CPDLParser::FindTearoffMethod(Token *pTearoff, LPCSTR pszTearoffMethod, LPSTR pszUseTearoff)
  601. {
  602. Token *pChildToken;
  603. CTokenListWalker ChildList(pTearoff);
  604. while (pChildToken = ChildList.GetNext())
  605. {
  606. if (pChildToken->GetType() == TYPE_TEAROFFMETHOD)
  607. {
  608. if (strcmp((LPCSTR)pChildToken->GetTagValue(TEAROFFMETHOD_NAME),
  609. pszTearoffMethod) == 0)
  610. {
  611. // Check if there is a class name in the method, if it is then
  612. // extract it explicity.
  613. strcpy(pszUseTearoff, (LPCSTR)pChildToken->GetTagValue(TEAROFFMETHOD_MAPTO));
  614. return TRUE;
  615. }
  616. }
  617. }
  618. // Call the super:: implementation except for the primary tearoff the base
  619. // implementation of each method if not specified is the current class.
  620. strcpy(pszUseTearoff, pTearoff->IsSet(TEAROFF_BASEIMPL) ?
  621. (LPCSTR)pTearoff->GetTagValue(TEAROFF_BASEIMPL) : "");
  622. strcat(pszUseTearoff, pszTearoffMethod);
  623. return FALSE;
  624. }
  625. // We exploit the Linker's Case insensitive feature to do Tearoffs in Win16.
  626. // This function takes a Tearoff Method and generates a name that is different
  627. // in case from the Real Tearoff Method. We have to follow certain rules so that
  628. // the compiler doesn't complain about undefined symbols and the linker puts in
  629. // the correct address anyhow.
  630. void GenerateWin16TearoffName(LPSTR szWin16Name, LPSTR pszTearoffMethod, LPSTR szClassName = NULL)
  631. {
  632. strcpy(szWin16Name, pszTearoffMethod);
  633. // if the Tearoff has a put_ or get_ prefix then we capitalize the PUT_
  634. // or GET_
  635. if ( !strncmp(szWin16Name, "put_", 4) )
  636. {
  637. strncpy(szWin16Name, "PUT_", 4);
  638. return;
  639. }
  640. if ( !strncmp(szWin16Name, "get_", 4) )
  641. {
  642. strncpy(szWin16Name, "GET_", 4);
  643. return;
  644. }
  645. // Check if there is a class name in the method, if it is super
  646. // then let it be else extract that and copy it to szClassName.
  647. char *p = strstr(szWin16Name, "::");
  648. if ( p && strncmp(szWin16Name, "super::",7) )
  649. {
  650. strcpy(pszTearoffMethod, p+2);
  651. if ( szClassName )
  652. {
  653. *p = '\0';
  654. strcpy(szClassName, szWin16Name);
  655. }
  656. strcpy(szWin16Name, pszTearoffMethod);
  657. }
  658. // lower case the name.
  659. _strlwr(szWin16Name);
  660. // make sure the generated name is different from the original one.
  661. if ( !strcmp( pszTearoffMethod, szWin16Name) )
  662. {
  663. char *p = strstr(szWin16Name, "::");
  664. // Ok, the Method name is all lower case, so we upper case the
  665. // name after the First char. We also need to skip past the Class Name
  666. // if any. Upper casing the whole name gave some other problems.
  667. if ( p != NULL )
  668. _strupr(p+2);
  669. else
  670. _strupr(szWin16Name+1);
  671. }
  672. }
  673. BOOL CPDLParser::GenerateTearoffTable ( Token *pClassToken, Token *pTearoff, LPCSTR pszInterface, BOOL fMostDerived )
  674. {
  675. fprintf ( fpHDLFile, "// Tear-off table for class %s\n",
  676. pClassToken -> GetTagValue ( CLASS_NAME ) );
  677. if (IsSpecialTearoff(pTearoff))
  678. {
  679. fprintf ( fpHDLFile, "BEGIN_TEAROFF_TABLE_PROPDESC(%s, %s)\n",
  680. pClassToken -> GetTagValue ( CLASS_NAME ),
  681. pszInterface );
  682. }
  683. else
  684. {
  685. fprintf ( fpHDLFile, "BEGIN_TEAROFF_TABLE(%s, %s)\n",
  686. pClassToken -> GetTagValue ( CLASS_NAME ),
  687. pszInterface );
  688. }
  689. // Walk the interface heirarchy, starting at this classes primary
  690. // interface, generate a fn table for each interface encountered
  691. // started with IDispatch methods above. Generate methods in interface order - deepest
  692. // first
  693. if ( !GenerateTearOffMethods ( pClassToken -> GetTagValue ( CLASS_NAME ), pTearoff, pszInterface, fMostDerived) )
  694. return FALSE;
  695. fprintf ( fpHDLFile, "END_TEAROFF_TABLE()\n\n" );
  696. return TRUE;
  697. }
  698. Token *CPDLParser::GetSuperClassTokenPtr ( Token *pClassToken )
  699. {
  700. Token *pSuperToken = NULL;
  701. if ( pClassToken -> IsSet ( CLASS_SUPER ) )
  702. {
  703. CTokenListWalker WholeList ( pRuntimeList );
  704. pSuperToken = WholeList.GetNext ( TYPE_CLASS,
  705. pClassToken -> GetTagValue ( CLASS_SUPER ) );
  706. }
  707. return pSuperToken;
  708. }
  709. BOOL CPDLParser::HasClassGotProperties ( Token *pClassToken )
  710. {
  711. Token *pSuperClass;
  712. CTokenListWalker PropList ( pClassToken );
  713. if ( PropList.GetNext ( TYPE_PROPERTY ) )
  714. return TRUE;
  715. else
  716. {
  717. pSuperClass = GetSuperClassTokenPtr ( pClassToken );
  718. if ( pSuperClass )
  719. return HasClassGotProperties ( pSuperClass );
  720. else
  721. return FALSE;
  722. }
  723. }
  724. BOOL CPDLParser::PrimaryTearoff (Token *pInterface)
  725. {
  726. return !pInterface->IsSet(INTERFACE_NOPRIMARYTEAROFF);
  727. }
  728. Token * CPDLParser::NextTearoff (LPCSTR szClassname, Token *pLastTearoff /*= NULL*/)
  729. {
  730. CTokenListWalker ThisFilesList(pRuntimeList, _pszPDLFileName);
  731. Token *pTearoffToken;
  732. BOOL fNextOne = FALSE;
  733. while (pTearoffToken = ThisFilesList.GetNext(TYPE_TEAROFF))
  734. {
  735. if (_stricmp(szClassname, (LPSTR)pTearoffToken->GetTagValue(TEAROFF_NAME)) == 0)
  736. {
  737. // The correct class.
  738. if (pLastTearoff)
  739. {
  740. // Return this one.
  741. if (!fNextOne)
  742. {
  743. fNextOne = pLastTearoff == pTearoffToken;
  744. continue; // Get the next and then stop.
  745. }
  746. }
  747. break;
  748. }
  749. }
  750. return pTearoffToken;
  751. }
  752. Token* CPDLParser::FindTearoff (LPCSTR szClassname, LPCSTR szInterface)
  753. {
  754. Token *pLastTearoff = NULL;
  755. while (pLastTearoff = NextTearoff(szClassname, pLastTearoff))
  756. {
  757. if (!_stricmp(szInterface, (LPSTR)pLastTearoff->GetTagValue(TEAROFF_INTERFACE)))
  758. {
  759. break;
  760. }
  761. }
  762. return pLastTearoff;
  763. }
  764. BOOL CPDLParser::GenerateClassIncludes (void)
  765. {
  766. Token *pClassToken;
  767. CTokenListWalker ThisFilesList(pRuntimeList, _pszPDLFileName);
  768. // Walk the class statments for this file only
  769. fprintf(fpLOGFile, "*** Looking for \"%s\"\n",_pszPDLFileName);
  770. while (pClassToken = ThisFilesList.GetNext(TYPE_CLASS))
  771. {
  772. LPCSTR szClassname = (LPCSTR)pClassToken->GetTagValue(CLASS_NAME);
  773. fprintf(fpHDLFile, "#ifdef _%s_\n\n", szClassname);
  774. // Write out inline cached get helpers
  775. fprintf(fpHDLFile,
  776. "\n// Cascaded Property get method prototypes for class %s\n\npublic:\n",
  777. szClassname);
  778. GenerateGetAAXPrototypes(pClassToken);
  779. fprintf(fpHDLFile,
  780. "\n// Property get/set method declarations for class %s\n",
  781. szClassname);
  782. // Always add a propdesc declaration for non-abstract classes, remember
  783. // abstract class haven't got a propertydesc array.
  784. // TODO: TerryLu - Need to add code here to handle the shared keyword
  785. if ((!pClassToken->IsSet(CLASS_ABSTRACT)) ||
  786. (_stricmp(pClassToken->GetTagValue(CLASS_NAME), "CElement") == 0))
  787. {
  788. if(_stricmp(pClassToken->GetTagValue(CLASS_NAME), "CElement") != 0)
  789. {
  790. fprintf(fpHDLFile,
  791. " static const HDLDESC %s::s_apHdlDescs;\n",
  792. szClassname);
  793. }
  794. fprintf(fpHDLFile,
  795. " static const CAssocVTable * const s_AssocVTablePtr[];\n");
  796. fprintf(fpHDLFile,
  797. " static const CAssocArrayVTable s_StringTable;\n");
  798. fprintf(fpHDLFile,
  799. " static const CPtrBagVTableAggregate s_StringTableAggregate;\n");
  800. if(_stricmp(pClassToken->GetTagValue(CLASS_NAME), "COmWindowProxy") == 0)
  801. {
  802. fprintf(fpHDLFile, "static const VTABLEDESC * const COmWindowProxy::s_COmWindowProxyDocument;\n");
  803. }
  804. }
  805. CString szInterface;
  806. Token *pInterface;
  807. BOOL fOk;
  808. Token *pTearoff = NULL;
  809. while ((pTearoff = NextTearoff(szClassname, pTearoff)))
  810. {
  811. szInterface = pTearoff->GetTagValue(TEAROFF_INTERFACE);
  812. pInterface = FindInterface(szInterface);
  813. if (pInterface)
  814. {
  815. CTokenListWalker ChildList(pInterface);
  816. Token *pChildToken = ChildList.GetNext();
  817. if (pChildToken)
  818. {
  819. fOk = FALSE;
  820. do
  821. {
  822. if (pChildToken->GetType() == TYPE_PROPERTY && !pChildToken->IsSet(PROPERTY_ABSTRACT) && !pChildToken->IsSet(PROPERTY_BASEIMPLEMENTATION))
  823. {
  824. fOk = TRUE;
  825. break;
  826. }
  827. } while (pChildToken = ChildList.GetNext());
  828. if (fOk)
  829. {
  830. fprintf(fpHDLFile, " static const PROPERTYDESC * const %s::s_ppropdescsInVtblOrder%s [];\n",
  831. szClassname, (LPSTR)pTearoff->GetTagValue(TEAROFF_INTERFACE));
  832. }
  833. }
  834. }
  835. }
  836. // Generate a CPC if, we have an eventset && it is unique to us
  837. if ( IsUniqueCPC ( pClassToken ) )
  838. {
  839. fprintf(fpHDLFile,
  840. " static const CONNECTION_POINT_INFO %s::s_acpi[];\n",
  841. szClassname);
  842. }
  843. GeneratePropMethodDecl(pClassToken);
  844. if (pClassToken->IsSet(CLASS_EVENTS))
  845. {
  846. if (!GenerateEventFireDecl(pClassToken))
  847. {
  848. return FALSE;
  849. }
  850. }
  851. // Whip thru all tearoffs.
  852. Token *pLastTearoff = NULL;
  853. while ((pLastTearoff = NextTearoff(szClassname, pLastTearoff)))
  854. {
  855. // Need static tearoff table decl
  856. if (IsSpecialTearoff(pLastTearoff))
  857. {
  858. fprintf(fpHDLFile, " DECLARE_TEAROFF_TABLE_PROPDESC(%s)\n",
  859. pLastTearoff->GetTagValue(TEAROFF_INTERFACE));
  860. }
  861. else
  862. {
  863. fprintf(fpHDLFile, " DECLARE_TEAROFF_TABLE(%s)\n",
  864. pLastTearoff->GetTagValue(TEAROFF_INTERFACE));
  865. }
  866. }
  867. GenerateThunkContext(pClassToken);
  868. fprintf(fpHDLFile, "\n#endif // _%s_\n\n", szClassname);
  869. fprintf(fpHDLFile, "#undef _%s_\n\n", szClassname);
  870. }
  871. return TRUE;
  872. }
  873. // Work out if this class has a unique connection point info structure -
  874. // or can we use its super ??
  875. BOOL CPDLParser::IsUniqueCPC ( Token *pClassToken )
  876. {
  877. BOOL fDoIt = FALSE;
  878. Token *pClass;
  879. CString szSuperClass, szThisEvents, szThatEvents;
  880. if ( !pClassToken->IsSet(CLASS_NOCPC) && pClassToken->IsSet ( CLASS_EVENTS ) )
  881. {
  882. szThisEvents = pClassToken->GetTagValue(CLASS_EVENTS);
  883. fDoIt = TRUE;
  884. for ( pClass = pClassToken ; pClass ; )
  885. {
  886. if ( pClass->IsSet ( CLASS_SUPER ) )
  887. {
  888. szSuperClass = pClass -> GetTagValue ( CLASS_SUPER );
  889. pClass = FindClass ( szSuperClass );
  890. if ( pClass && pClass->IsSet ( CLASS_EVENTS ) && !pClass->IsSet(CLASS_NOCPC) )
  891. {
  892. szThatEvents = pClass->GetTagValue(CLASS_EVENTS);
  893. if ( szThatEvents == szThisEvents )
  894. {
  895. // Do we have non-primary events #1 and is the super non-primary events
  896. // the same as ours? If not, then we are unique.
  897. if (pClassToken->IsSet(CLASS_NONPRIMARYEVENTS1))
  898. {
  899. szThisEvents = pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS1);
  900. szThatEvents = pClass->GetTagValue(CLASS_NONPRIMARYEVENTS1);
  901. if (szThatEvents != szThisEvents)
  902. {
  903. // We're unique.
  904. break;
  905. }
  906. // Do we have non-primary events #2 and is the super non-primary events
  907. // the same as ours? If not, then we are unique.
  908. if (pClassToken->IsSet(CLASS_NONPRIMARYEVENTS2))
  909. {
  910. szThisEvents = pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS2);
  911. szThatEvents = pClass->GetTagValue(CLASS_NONPRIMARYEVENTS2);
  912. if (szThatEvents != szThisEvents)
  913. {
  914. // We're unique.
  915. break;
  916. }
  917. // Do we have non-primary events #3 and is the super non-primary events
  918. // the same as ours? If not, then we are unique.
  919. if (pClassToken->IsSet(CLASS_NONPRIMARYEVENTS3))
  920. {
  921. szThisEvents = pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS3);
  922. szThatEvents = pClass->GetTagValue(CLASS_NONPRIMARYEVENTS3);
  923. if (szThatEvents != szThisEvents)
  924. {
  925. // We're unique.
  926. break;
  927. }
  928. // Do we have non-primary events #4 and is the super non-primary events
  929. // the same as ours? If not, then we are unique.
  930. if (pClassToken->IsSet(CLASS_NONPRIMARYEVENTS4))
  931. {
  932. szThisEvents = pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS4);
  933. szThatEvents = pClass->GetTagValue(CLASS_NONPRIMARYEVENTS4);
  934. if (szThatEvents != szThisEvents)
  935. {
  936. // We're unique.
  937. break;
  938. }
  939. }
  940. }
  941. }
  942. // else fall through to below which set's fDoIt to FALSE.
  943. }
  944. fDoIt = FALSE;
  945. break;
  946. }
  947. break;
  948. }
  949. }
  950. else
  951. break;
  952. }
  953. }
  954. return fDoIt;
  955. }
  956. BOOL CPDLParser::GenerateEventFireDecl ( Token *pClassToken )
  957. {
  958. Token *pEventToken;
  959. fprintf ( fpHDLFile, "// Event fire method declarations for events %s\n",
  960. pClassToken -> GetTagValue ( CLASS_EVENTS ) );
  961. // Find the event declaration
  962. CTokenListWalker WholeList ( pRuntimeList ) ;
  963. pEventToken = WholeList.GetNext ( TYPE_EVENT, pClassToken -> GetTagValue ( CLASS_EVENTS ) );
  964. if ( pEventToken == NULL )
  965. {
  966. return FALSE;
  967. }
  968. return GenerateEventDecl ( pClassToken, pEventToken );
  969. }
  970. BOOL CPDLParser::IsElementEvent(Token *pEventInterface)
  971. {
  972. CTokenListWalker WholeList(pRuntimeList);
  973. CString szEvent;
  974. CString szElementEvent;
  975. if (!pEventInterface)
  976. return FALSE;
  977. szEvent = pEventInterface->GetTagValue(EVENT_NAME);
  978. if (_stricmp((LPCSTR)szEvent, "HTMLObjectElementEvents") == 0)
  979. return TRUE;
  980. szElementEvent = "HTMLElementEvents";
  981. while (pEventInterface)
  982. {
  983. if (szElementEvent == szEvent)
  984. return TRUE;
  985. szEvent = pEventInterface->GetTagValue(EVENT_SUPER);
  986. WholeList.Reset();
  987. pEventInterface = WholeList.GetNext(TYPE_EVENT, szEvent);
  988. }
  989. return FALSE;
  990. }
  991. BOOL CPDLParser::GenerateEventDecl ( Token *pClassToken, Token *pEventToken )
  992. {
  993. /* TLL: Don't spit out any arguments. Currently the only argument for event is eventObject which is computed
  994. Token *pArgToken;
  995. */
  996. Token *pChildToken;
  997. char szErrorText [ MAX_LINE_LEN+1 ];
  998. CTokenListWalker ChildList ( pEventToken );
  999. CString szNameUpper;
  1000. CString szNameLower;
  1001. BOOL fDocEvents = (_stricmp(pClassToken->GetTagValue(CLASS_EVENTS), "HTMLDocumentEvents") == 0) ||
  1002. (_stricmp(pClassToken->GetTagValue(CLASS_EVENTS), "HTMLProtectedElementEvents") == 0) ||
  1003. (_stricmp(pClassToken->GetTagValue(CLASS_EVENTS), "HTMLNamespaceEvents") == 0);
  1004. BOOL fWindowEvents = _stricmp(pClassToken->GetTagValue(CLASS_EVENTS), "HTMLWindowEvents") == 0;
  1005. BOOL fElementEvents = !fDocEvents && !fWindowEvents && IsElementEvent(pEventToken);
  1006. while ( pChildToken = ChildList.GetNext() )
  1007. {
  1008. if (!fElementEvents && !fDocEvents && !fWindowEvents &&
  1009. (_stricmp(pClassToken->GetTagValue(CLASS_EVENTS), "DWebBridgeEvents") != 0))
  1010. {
  1011. sprintf ( szErrorText, "Need to modify GenerateEventDecl() in parser.cpp to pass in Doc ptr to FireEvent for class:%s\n",
  1012. (LPCSTR)pClassToken->GetTagValue(CLASS_NAME) );
  1013. ReportError ( szErrorText );
  1014. return FALSE;
  1015. }
  1016. if ( pChildToken -> GetType() == TYPE_METHOD &&
  1017. !pChildToken -> IsSet ( METHOD_ABSTRACT ) )
  1018. {
  1019. szNameUpper = pChildToken -> GetTagValue ( METHOD_NAME );
  1020. szNameLower = szNameUpper;
  1021. szNameUpper.ToUpper();
  1022. if (!FindEventProp(pClassToken, (LPCSTR)szNameLower))
  1023. continue;
  1024. // Method
  1025. fprintf ( fpHDLFile, " %s Fire_%s(",
  1026. pChildToken->IsSet(METHOD_CANCELABLE) ? "BOOL" : "void",
  1027. pChildToken -> GetTagValue ( METHOD_NAME ) );
  1028. CTokenListWalker ArgListWalker ( pChildToken );
  1029. BOOL fFirst = TRUE;
  1030. /* TLL: Don't spit out any arguments. Currently the only argument for event is eventObject which is computed
  1031. while ( pArgToken = ArgListWalker.GetNext() )
  1032. {
  1033. if ( !fFirst )
  1034. fprintf ( fpHDLFile, "," );
  1035. fprintf ( fpHDLFile, "%s %s",
  1036. (LPCSTR)pArgToken -> GetTagValue ( METHODARG_TYPE ),
  1037. (LPCSTR)pArgToken -> GetTagValue ( METHODARG_ARGNAME ));
  1038. fFirst = FALSE;
  1039. }
  1040. */
  1041. if ( pChildToken->IsSet(METHOD_BUBBLING) )
  1042. {
  1043. if ( !fFirst )
  1044. fprintf ( fpHDLFile, "," );
  1045. fprintf ( fpHDLFile, "CTreeNode * pNodeContext = NULL");
  1046. fprintf ( fpHDLFile, ", long lSubDivision = -1");
  1047. }
  1048. fprintf ( fpHDLFile, ")\n {\n " );
  1049. if ( pChildToken->IsSet(METHOD_CANCELABLE) )
  1050. {
  1051. fprintf ( fpHDLFile, "return !!" );
  1052. }
  1053. if (fElementEvents)
  1054. {
  1055. fprintf(fpHDLFile, "FireEvent(&s_propdesc%s%s%s",
  1056. (LPCSTR)pClassToken->GetTagValue(CLASS_NAME),
  1057. (LPCSTR)szNameLower,
  1058. pChildToken->IsSet(METHOD_BUBBLING) ? ", TRUE, pNodeContext, lSubDivision" : "");
  1059. }
  1060. else
  1061. {
  1062. fprintf(fpHDLFile, "FireEvent(%sDISPID_EVMETH_%s, DISPID_EVPROP_%s, _T(\"%s\")",
  1063. fDocEvents ? "Doc(), " : (fWindowEvents ? "_pDoc, " : ""),
  1064. (LPCSTR)szNameUpper,
  1065. (LPCSTR)szNameUpper,
  1066. (LPCSTR)szNameLower+2);
  1067. }
  1068. /* TLL: Don't spit out any arguments. Currently the only argument for event is eventObject which is computed
  1069. ArgListWalker.Reset();
  1070. if ( ArgListWalker.GetTokenCount() > 0 )
  1071. {
  1072. while ( pArgToken = ArgListWalker.GetNext() )
  1073. {
  1074. // Locate the vts type for this type
  1075. CString szVTSType;
  1076. if ( !LookupEventType ( szVTSType, pArgToken -> GetTagValue ( METHODARG_TYPE ) ) )
  1077. {
  1078. sprintf ( szErrorText, "Unknown Type %s in %s::Fire%s event declaration\n",
  1079. (LPCSTR) pArgToken -> GetTagValue ( METHODARG_TYPE ),
  1080. pEventToken -> GetTagValue ( EVENT_NAME ),
  1081. pChildToken -> GetTagValue ( METHOD_NAME ) );
  1082. ReportError ( szErrorText );
  1083. return FALSE;
  1084. }
  1085. fprintf ( fpHDLFile, " %s", (LPCSTR)szVTSType );
  1086. fFirst = FALSE;
  1087. }
  1088. ArgListWalker.Reset();
  1089. while ( pArgToken = ArgListWalker.GetNext() )
  1090. {
  1091. fprintf ( fpHDLFile, ", %s",
  1092. pArgToken -> GetTagValue ( METHODARG_ARGNAME ) );
  1093. }
  1094. }
  1095. else
  1096. {
  1097. fprintf ( fpHDLFile, " VTS_NONE" );
  1098. }
  1099. */
  1100. fprintf ( fpHDLFile, ");\n }\n" );
  1101. }
  1102. else if ( pChildToken -> GetType() == TYPE_PROPERTY )
  1103. {
  1104. // Property in event set - should never happen if we
  1105. // check the child/parent relationships at parse time
  1106. sprintf ( szErrorText, "events %s - invalid to have a property in event set\n",
  1107. (LPCSTR)pClassToken -> GetTagValue ( EVENT_NAME ) );
  1108. ReportError ( szErrorText );
  1109. return FALSE;
  1110. }
  1111. }
  1112. return TRUE;
  1113. }
  1114. LPCSTR CPDLParser::ConvertType(LPCSTR szType, BOOL fComPlus /* = FALSE*/, LPSTR pCPString /* = 0*/, BOOL *pfInterfaceFound /* = 0*/)
  1115. {
  1116. if (!fComPlus)
  1117. {
  1118. if (_stricmp(szType, "SAFEARRAY(VARIANT)") == 0)
  1119. return("SAFEARRAY*");
  1120. else
  1121. return(szType);
  1122. }
  1123. else
  1124. {
  1125. BOOL fInterfFound;
  1126. if (!pfInterfaceFound)
  1127. {
  1128. pfInterfaceFound = &fInterfFound;
  1129. }
  1130. *pfInterfaceFound = FALSE;
  1131. if (_stricmp(szType, "BSTR") == 0)
  1132. return("String");
  1133. else if (_stricmp(szType, "VARIANT_BOOL") == 0)
  1134. return("Boolean");
  1135. else if (_stricmp(szType, "VARIANT") == 0)
  1136. return("Variant");
  1137. else if (_stricmp(szType, "IDispatch") == 0 || _stricmp(szType, "IUnknown") == 0)
  1138. return("Object");
  1139. else if (_stricmp(szType, "SAFEARRAY(VARIANT)") == 0)
  1140. return("String"); // ***TLL*** COM+: Need to make it a safearray
  1141. else if (pCPString)
  1142. {
  1143. CString pInterf;
  1144. pInterf = szType;
  1145. if (FindInterface(pInterf))
  1146. {
  1147. strcpy(pCPString, szType);
  1148. strcat(pCPString, "COMPLUS");
  1149. *pfInterfaceFound = TRUE;
  1150. return 0;
  1151. }
  1152. else
  1153. {
  1154. return(szType);
  1155. }
  1156. }
  1157. else
  1158. return(szType);
  1159. }
  1160. }
  1161. void CPDLParser::GeneratePropMethodDecl ( Token *pClassToken )
  1162. {
  1163. CTokenListWalker ChildList ( pClassToken );
  1164. CString szProp;
  1165. Token *pArgToken;
  1166. Token *pChildToken;
  1167. char szContextThunk[] = "ContextThunk_";
  1168. LPCSTR pCtxt;
  1169. while ( pChildToken = ChildList.GetNext() )
  1170. {
  1171. char szTemp[256];
  1172. LPSTR pMethodName;
  1173. BOOL fNameOnly;
  1174. fNameOnly = _stricmp(pChildToken->GetTagValue(METHOD_NOPROPDESC), "nameonly") == 0;
  1175. if ( pChildToken -> GetType() == TYPE_METHOD && !fNameOnly )
  1176. {
  1177. // Method
  1178. fprintf ( fpHDLFile, " " );
  1179. if ( pChildToken -> IsSet ( METHOD_VIRTUAL ) )
  1180. {
  1181. //fprintf ( fpHDLFile, "virtual " );
  1182. fprintf ( fpHDLFile, "DECLARE_TEAROFF_METHOD_(" );
  1183. }
  1184. else
  1185. fprintf ( fpHDLFile, "NV_DECLARE_TEAROFF_METHOD_(" );
  1186. pMethodName = pChildToken->IsSet(METHOD_SZINTERFACEEXPOSE) ?
  1187. (LPSTR)pChildToken->GetTagValue(METHOD_SZINTERFACEEXPOSE) :
  1188. (LPSTR)pChildToken->GetTagValue(METHOD_NAME);
  1189. GenerateWin16TearoffName(szTemp, pMethodName);
  1190. pCtxt = pChildToken->IsSet(METHOD_THUNKCONTEXT) ||
  1191. pChildToken->IsSet(METHOD_THUNKNODECONTEXT)
  1192. ? szContextThunk : "";
  1193. //fprintf ( fpHDLFile, "%s STDMETHODCALLTYPE %s(",
  1194. fprintf ( fpHDLFile, "%s, %s%s, %s, (",
  1195. pChildToken -> GetTagValue ( METHOD_RETURNTYPE ),
  1196. pCtxt, pMethodName, szTemp );
  1197. CTokenListWalker ArgListWalker ( pChildToken );
  1198. BOOL fFirst = TRUE;
  1199. while ( pArgToken = ArgListWalker.GetNext() )
  1200. {
  1201. if ( !fFirst )
  1202. fprintf ( fpHDLFile, "," );
  1203. fprintf ( fpHDLFile, "%s %s",
  1204. ConvertType((LPCSTR)pArgToken -> GetTagValue ( METHODARG_TYPE )),
  1205. (LPCSTR)pArgToken -> GetTagValue ( METHODARG_ARGNAME ) );
  1206. fFirst = FALSE;
  1207. }
  1208. fprintf ( fpHDLFile, "));\n" );
  1209. }
  1210. else
  1211. {
  1212. fNameOnly = _stricmp(pChildToken->GetTagValue(PROPERTY_NOPROPDESC), "nameonly") == 0;
  1213. // Base has provided prototoype
  1214. if ( pChildToken -> IsSet ( PROPERTY_BASEIMPLEMENTATION )
  1215. || (!pChildToken->IsSet(PROPERTY_ABSTRACT) && IsSpecialProperty(pClassToken))
  1216. )
  1217. {
  1218. continue;
  1219. }
  1220. // Property
  1221. szProp = "";
  1222. // Through the index/indextype & index1/indextype1 pdl tags
  1223. // you can provide up to two additional args for the property definition
  1224. if ( pChildToken -> IsSet ( PROPERTY_INDEX ) )
  1225. {
  1226. szProp += pChildToken -> GetTagValue ( PROPERTY_INDEXTYPE );
  1227. szProp += " ";
  1228. szProp += pChildToken -> GetTagValue ( PROPERTY_INDEX );
  1229. }
  1230. if ( pChildToken -> IsSet ( PROPERTY_INDEX1 ) )
  1231. {
  1232. if ( szProp [ 0 ] != '\0' )
  1233. szProp += ",";
  1234. szProp += pChildToken -> GetTagValue ( PROPERTY_INDEXTYPE1 );
  1235. szProp += " ";
  1236. szProp += pChildToken -> GetTagValue ( PROPERTY_INDEX1 );
  1237. }
  1238. if ( szProp [ 0 ] != '\0' )
  1239. szProp += ",";
  1240. pMethodName = pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
  1241. (LPSTR)pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
  1242. (LPSTR)pChildToken->GetTagValue(PROPERTY_NAME);
  1243. pCtxt = pChildToken->IsSet(PROPERTY_THUNKCONTEXT) ||
  1244. pChildToken->IsSet(PROPERTY_THUNKNODECONTEXT)
  1245. ? szContextThunk : "";
  1246. if ( pChildToken -> IsSet ( PROPERTY_SET ) && !fNameOnly )
  1247. {
  1248. fprintf ( fpHDLFile, " " );
  1249. if ( pChildToken -> IsSet ( PROPERTY_VIRTUAL ) )
  1250. {
  1251. fprintf ( fpHDLFile, "DECLARE_TEAROFF_METHOD(%sput_%s, PUT_%s, (%s%s v));\n",
  1252. pCtxt,
  1253. pMethodName,
  1254. pMethodName,
  1255. (LPCSTR)szProp,
  1256. (LPCSTR)pChildToken -> GetTagValue ( PROPERTY_ATYPE ));
  1257. }
  1258. else
  1259. {
  1260. fprintf ( fpHDLFile, "NV_DECLARE_TEAROFF_METHOD(%sput_%s, PUT_%s, (%s%s v));\n",
  1261. pCtxt,
  1262. pMethodName,
  1263. pMethodName,
  1264. (LPCSTR)szProp,
  1265. (LPCSTR)pChildToken -> GetTagValue ( PROPERTY_ATYPE ));
  1266. }
  1267. }
  1268. if ( pChildToken -> IsSet ( PROPERTY_GET ) && !fNameOnly)
  1269. {
  1270. fprintf ( fpHDLFile, " " );
  1271. if ( pChildToken -> IsSet ( PROPERTY_VIRTUAL ) )
  1272. {
  1273. fprintf ( fpHDLFile, "DECLARE_TEAROFF_METHOD(%sget_%s, GET_%s, (%s%s*p));\n",
  1274. pCtxt,
  1275. pMethodName,
  1276. pMethodName,
  1277. (LPCSTR)szProp,
  1278. (LPCSTR)pChildToken -> GetTagValue ( PROPERTY_ATYPE ));
  1279. }
  1280. else
  1281. {
  1282. fprintf ( fpHDLFile, "NV_DECLARE_TEAROFF_METHOD(%sget_%s, GET_%s, (%s%s*p));\n",
  1283. pCtxt,
  1284. pMethodName,
  1285. pMethodName,
  1286. (LPCSTR)szProp,
  1287. (LPCSTR)pChildToken -> GetTagValue ( PROPERTY_ATYPE ));
  1288. }
  1289. }
  1290. }
  1291. }
  1292. }
  1293. BOOL CPDLParser::IsStoredAsString( Token *pChildToken )
  1294. {
  1295. CString szJunk1, szJunk2;
  1296. StorageType stHowStored;
  1297. GetTypeDetails ( pChildToken->GetTagValue ( PROPERTY_TYPE ),
  1298. szJunk1, szJunk2, &stHowStored );
  1299. return stHowStored == STORAGETYPE_STRING ? TRUE : FALSE;
  1300. }
  1301. void CPDLParser::GenerateGetAAXPrototypes ( Token *pClassToken )
  1302. {
  1303. CTokenListWalker ChildList ( pClassToken );
  1304. Token *pChildToken;
  1305. if ( pClassToken -> IsSet ( CLASS_NOAAMETHODS ) )
  1306. return;
  1307. while ( pChildToken = ChildList.GetNext() )
  1308. {
  1309. // Generate a GetAA prototype even if the automation Get method is not generated
  1310. if ( pChildToken -> GetType() != TYPE_METHOD &&
  1311. pChildToken -> IsSet ( PROPERTY_CAA ) &&
  1312. _stricmp(pChildToken->GetTagValue(PROPERTY_NOPROPDESC), "nameonly"))
  1313. {
  1314. BOOL fIsString = IsStoredAsString(pChildToken);
  1315. //setaahr method
  1316. if (pChildToken -> IsSet ( PROPERTY_SETAAHR ) )
  1317. {
  1318. fprintf ( fpHDLFile, " HRESULT SetAA%s(%s);\n",
  1319. (LPCSTR)pChildToken -> GetTagValue ( PROPERTY_NAME ),
  1320. (LPCSTR)(fIsString?"LPCTSTR": (LPCSTR)pChildToken -> GetTagValue ( PROPERTY_TYPE ) )
  1321. );
  1322. }
  1323. //get method. If the property refers to a cascaded format - don't generate a GetAA - this would just
  1324. // encourage mis-use. Always want to force use of GetCascadedXX variant
  1325. if ( !pChildToken -> IsSet ( PROPERTY_CASCADED ) ||
  1326. pChildToken -> IsSet ( PROPERTY_GETAA ) )
  1327. {
  1328. fprintf ( fpHDLFile, " %s GetAA%s() const;\n",
  1329. (LPCSTR)(fIsString?"LPCTSTR":(LPCSTR)pChildToken -> GetTagValue ( PROPERTY_TYPE )),
  1330. (LPCSTR)(pChildToken->GetTagValue ( PROPERTY_NAME )) );
  1331. }
  1332. }
  1333. }
  1334. }
  1335. void CPDLParser::GenerateGetAAXImplementations( Token *pClassToken )
  1336. {
  1337. CTokenListWalker ChildList ( pClassToken );
  1338. Token *pChildToken;
  1339. if ( pClassToken -> IsSet ( CLASS_NOAAMETHODS ) )
  1340. return;
  1341. while ( pChildToken = ChildList.GetNext() )
  1342. {
  1343. // Generate a GetAA prototype even if the automation Get method is not generated
  1344. if ( pChildToken -> GetType() != TYPE_METHOD &&
  1345. pChildToken -> IsSet ( PROPERTY_CAA ) &&
  1346. _stricmp(pChildToken->GetTagValue(PROPERTY_NOPROPDESC), "nameonly"))
  1347. {
  1348. BOOL fIsString = IsStoredAsString(pChildToken);
  1349. //setaahr method
  1350. if (pChildToken -> IsSet ( PROPERTY_SETAAHR ) )
  1351. {
  1352. if (!strcmp((LPCSTR)pChildToken ->GetTagValue(PROPERTY_TYPE), "VARIANT_BOOL"))
  1353. {
  1354. 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",
  1355. (LPCSTR)pClassToken -> GetTagValue ( CLASS_NAME ),
  1356. (LPCSTR)pChildToken -> GetTagValue ( PROPERTY_NAME ),
  1357. (LPCSTR)pClassToken -> GetTagValue ( CLASS_NAME ),
  1358. (LPCSTR)pChildToken -> GetTagValue ( PROPERTY_NAME )
  1359. );
  1360. }
  1361. else
  1362. {
  1363. fprintf ( fpHDLFile, "HRESULT %s::SetAA%s(%s pv)\n{\n RRETURN( THR( CAttrArray::Set%s(GetAttrArray(), &s_propdesc%s%s.a, %spv) ) );\n}\n",
  1364. (LPCSTR)pClassToken -> GetTagValue ( CLASS_NAME ),
  1365. (LPCSTR)pChildToken -> GetTagValue ( PROPERTY_NAME ),
  1366. (LPCSTR)( fIsString?"LPCTSTR":(LPCSTR)pChildToken ->GetTagValue(PROPERTY_TYPE) ),
  1367. (LPCSTR)(fIsString?"String":"Simple"),
  1368. (LPCSTR)pClassToken -> GetTagValue ( CLASS_NAME ),
  1369. (LPCSTR)pChildToken -> GetTagValue ( PROPERTY_NAME ),
  1370. (LPCSTR)(fIsString?"":"*(DWORD*) &")
  1371. );
  1372. }
  1373. }
  1374. //get method. Don't generate a GetAA - they already have a GetCascadedX
  1375. if ( !pChildToken -> IsSet ( PROPERTY_CASCADED ) ||
  1376. pChildToken -> IsSet ( PROPERTY_GETAA ) )
  1377. {
  1378. Token *pExposeToken = NULL;
  1379. CString szClass;
  1380. if (pChildToken -> IsSet ( PROPERTY_NOPROPDESC ))
  1381. {
  1382. pExposeToken = FindMatchingEntryWOPropDesc(pClassToken, pChildToken);
  1383. }
  1384. if (!pExposeToken)
  1385. pExposeToken = pChildToken;
  1386. if (strlen( pExposeToken -> GetTagValue ( PROPERTY_REFDTOCLASS )))
  1387. szClass = pExposeToken -> GetTagValue ( PROPERTY_REFDTOCLASS );
  1388. else
  1389. szClass = (LPCSTR)pClassToken -> GetTagValue ( CLASS_NAME );
  1390. #ifdef UNIX // IEUNIX: On Unix, converting DWORD* to short* would cause value changed. So we cast it from DWORD to short.
  1391. if (!fIsString)
  1392. {
  1393. LPCSTR pPropType = (LPCSTR)pChildToken->GetTagValue( PROPERTY_TYPE);
  1394. if ( !_stricmp(pPropType , "short") || !_stricmp(pPropType, "WORD") || !_stricmp(pPropType, "BYTE") )
  1395. {
  1396. 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",
  1397. pPropType,
  1398. (LPCSTR)pClassToken -> GetTagValue ( CLASS_NAME ),
  1399. (LPCSTR)(pChildToken->GetTagValue ( PROPERTY_NAME )),
  1400. (LPCSTR)szClass,
  1401. (LPCSTR)pChildToken -> GetTagValue ( PROPERTY_NAME ),
  1402. pPropType );
  1403. continue;
  1404. }
  1405. }
  1406. #endif
  1407. 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",
  1408. (LPCSTR)(fIsString?"LPCTSTR":(LPCSTR)pChildToken -> GetTagValue ( PROPERTY_TYPE )),
  1409. (LPCSTR)pClassToken -> GetTagValue ( CLASS_NAME ),
  1410. (LPCSTR)(pChildToken->GetTagValue ( PROPERTY_NAME )) ,
  1411. (LPCSTR)(fIsString?"LPCTSTR":"DWORD" ),
  1412. (LPCSTR)(fIsString?"String":"Simple"),
  1413. (LPCSTR)szClass,
  1414. (LPCSTR)pChildToken -> GetTagValue ( PROPERTY_NAME ),
  1415. (LPCSTR)(fIsString?"LPCTSTR":(LPCSTR)pChildToken -> GetTagValue ( PROPERTY_TYPE ) ) );
  1416. }
  1417. }
  1418. }
  1419. }
  1420. BOOL CPDLParser::GenerateIDispatchTearoff ( LPCSTR szClassName, Token *pTearoff, LPCSTR pszInterface, BOOL fMostDerived)
  1421. {
  1422. char szTearoffMethod[128];
  1423. char szTemp[128];
  1424. fprintf ( fpHDLFile, " // IDispatch methods\n");
  1425. FindTearoffMethod(pTearoff, "GetTypeInfoCount", szTearoffMethod);
  1426. GenerateWin16TearoffName(szTemp, szTearoffMethod);
  1427. fprintf ( fpHDLFile, " TEAROFF_METHOD(%s, %s, %s, (unsigned int *))\n",
  1428. szClassName, szTearoffMethod, szTemp);
  1429. FindTearoffMethod(pTearoff, "GetTypeInfo", szTearoffMethod);
  1430. GenerateWin16TearoffName(szTemp, szTearoffMethod);
  1431. fprintf ( fpHDLFile, " TEAROFF_METHOD(%s, %s, %s, (unsigned int, unsigned long, ITypeInfo **))\n",
  1432. szClassName, szTearoffMethod, szTemp);
  1433. FindTearoffMethod(pTearoff, "GetIDsOfNames", szTearoffMethod);
  1434. GenerateWin16TearoffName(szTemp, szTearoffMethod);
  1435. fprintf ( fpHDLFile, " TEAROFF_METHOD(%s, %s, %s, (REFIID, LPOLESTR *, unsigned int, LCID, DISPID *))\n",
  1436. szClassName, szTearoffMethod, szTemp);
  1437. {
  1438. CString szIHTMLElement, szInterface;
  1439. szIHTMLElement = "IHTMLElement";
  1440. szInterface = pszInterface;
  1441. if(!FindTearoffMethod(pTearoff, "Invoke", szTearoffMethod) &&
  1442. IsSuperInterface(szIHTMLElement, FindInterface(szInterface)))
  1443. {
  1444. strcpy(szTearoffMethod, pTearoff->IsSet(TEAROFF_BASEIMPL) ?
  1445. (LPCSTR)pTearoff->GetTagValue(TEAROFF_BASEIMPL) : "");
  1446. strcat(szTearoffMethod, "ContextThunk_Invoke");
  1447. }
  1448. }
  1449. GenerateWin16TearoffName(szTemp, szTearoffMethod);
  1450. fprintf ( fpHDLFile, " TEAROFF_METHOD(%s, %s, %s, (DISPID, REFIID, LCID, WORD, DISPPARAMS *, VARIANT *, EXCEPINFO *, unsigned int *))\n",
  1451. szClassName, szTearoffMethod, szTemp);
  1452. return TRUE;
  1453. }
  1454. BOOL CPDLParser::IsSpecialTearoff(Token *pTearoff)
  1455. {
  1456. CString szInterface;
  1457. Token *pInterface;
  1458. Token *pChildToken;
  1459. szInterface = pTearoff->GetTagValue(TEAROFF_INTERFACE);
  1460. pInterface = FindInterface(szInterface);
  1461. if (!pInterface || pInterface->IsSet(INTERFACE_ABSTRACT))
  1462. return FALSE;
  1463. CTokenListWalker ChildList(pInterface);
  1464. pChildToken = ChildList.GetNext();
  1465. if (pChildToken)
  1466. {
  1467. do
  1468. {
  1469. if (pChildToken->GetType() == TYPE_PROPERTY && !pChildToken->IsSet(PROPERTY_ABSTRACT) && !pChildToken->IsSet(PROPERTY_BASEIMPLEMENTATION))
  1470. {
  1471. return TRUE;
  1472. }
  1473. } while (pChildToken = ChildList.GetNext());
  1474. }
  1475. return FALSE;
  1476. }
  1477. BOOL CPDLParser::FindTearoffProperty(Token *pPropertyToken, LPSTR szTearoffMethod,
  1478. LPSTR szTearOffClassName, LPSTR szPropArgs, BOOL fPropGet)
  1479. {
  1480. if (pPropertyToken->IsSet(PROPERTY_ABSTRACT) || pPropertyToken->IsSet(PROPERTY_BASEIMPLEMENTATION))
  1481. return FALSE;
  1482. strcpy(szTearoffMethod, fPropGet ? "get_" : "put_");
  1483. strcpy(szPropArgs, fPropGet ? "void" : (LPCSTR)pPropertyToken->GetTagValue(PROPERTY_ATYPE));
  1484. strcpy(szTearOffClassName, "CBase");
  1485. if (!strcmp(pPropertyToken->GetTagValue(PROPERTY_ATYPE), "VARIANT"))
  1486. {
  1487. if (fPropGet)
  1488. {
  1489. strcat(szTearoffMethod, "Property");
  1490. }
  1491. else if (pPropertyToken->IsSet(PROPERTY_DATAEVENT))
  1492. strcat(szTearoffMethod, "DataEvent");
  1493. else
  1494. strcat(szTearoffMethod, "Variant");
  1495. }
  1496. else if (!strcmp(pPropertyToken->GetTagValue(PROPERTY_ATYPE), "BSTR"))
  1497. {
  1498. if (!strcmp(pPropertyToken->GetTagValue(PROPERTY_TYPE), "url"))
  1499. {
  1500. strcat(szTearoffMethod, "Url");
  1501. strcpy(szPropArgs, (LPCSTR)pPropertyToken->GetTagValue(PROPERTY_ATYPE));
  1502. }
  1503. else if (!strcmp(pPropertyToken->GetTagValue(PROPERTY_TYPE), "CStyleComponent"))
  1504. {
  1505. strcat(szTearoffMethod, "StyleComponent");
  1506. strcpy(szPropArgs, (LPCSTR)pPropertyToken->GetTagValue(PROPERTY_ATYPE));
  1507. }
  1508. else
  1509. strcat(szTearoffMethod, (fPropGet ? "Property" : "String"));
  1510. }
  1511. else if (!strcmp(pPropertyToken->GetTagValue(PROPERTY_ATYPE), "VARIANT_BOOL"))
  1512. strcat(szTearoffMethod, (fPropGet ? "Property" : "Bool"));
  1513. else if (!strcmp(pPropertyToken->GetTagValue(PROPERTY_ATYPE), "long"))
  1514. strcat(szTearoffMethod, fPropGet ? "Property" : "Long");
  1515. else if (!strcmp(pPropertyToken->GetTagValue(PROPERTY_ATYPE), "short"))
  1516. strcat(szTearoffMethod, fPropGet ? "Property" : "Short");
  1517. else
  1518. {
  1519. char szError[124];
  1520. sprintf(szError, "%s: This property of new type needs a function prototype (in cdbase.hxx) and a body defn. in (baseprop.cxx)",
  1521. (LPCSTR)pPropertyToken->GetTagValue(PROPERTY_NAME));
  1522. ReportError (szError);
  1523. return FALSE;
  1524. }
  1525. return TRUE;
  1526. }
  1527. BOOL CPDLParser::GeneratePropDescsInVtblOrder(Token *pClassToken, int *pNumVtblPropDescs)
  1528. {
  1529. CString szPrimaryInterf;
  1530. CString szInterface;
  1531. LPCSTR szClassName = pClassToken->GetTagValue(CLASS_NAME);
  1532. BOOL fOk;
  1533. BOOL fNameOnly;
  1534. int i = 0, j;
  1535. szPrimaryInterf = pClassToken->GetTagValue(CLASS_INTERFACE);
  1536. Token *pPrimaryInterf = FindInterface(szPrimaryInterf);
  1537. Token *pInterface;
  1538. Token *pChildToken;
  1539. Token *apInterface[5];
  1540. *pNumVtblPropDescs = 0;
  1541. Token *pTearoff = NULL;
  1542. while ((pTearoff = NextTearoff(szClassName, pTearoff)))
  1543. {
  1544. szInterface = pTearoff->GetTagValue(TEAROFF_INTERFACE);
  1545. pInterface = FindInterface(szInterface);
  1546. if (!pInterface || pInterface->IsSet(INTERFACE_ABSTRACT))
  1547. continue;
  1548. i = 0;
  1549. apInterface[i++] = pInterface;
  1550. while (i < 5 && apInterface[i-1]->IsSet(INTERFACE_SUPER) &&
  1551. _stricmp(apInterface[i-1]->GetTagValue(INTERFACE_SUPER), "IDispatch") &&
  1552. _stricmp(apInterface[i-1]->GetTagValue(INTERFACE_SUPER), "IUnknown"))
  1553. {
  1554. szInterface = apInterface[i-1]->GetTagValue(INTERFACE_SUPER);
  1555. apInterface[i++] = FindInterface(szInterface);
  1556. }
  1557. if (i >= 5)
  1558. {
  1559. ReportError("Super Chain More than 5, Need to increase limit in PdlParser");
  1560. return FALSE;
  1561. }
  1562. fOk = FALSE;
  1563. CTokenListWalker ChildList(pInterface);
  1564. pChildToken = ChildList.GetNext();
  1565. if (pChildToken)
  1566. {
  1567. do
  1568. {
  1569. if (pChildToken->GetType() == TYPE_PROPERTY && !pChildToken->IsSet(PROPERTY_ABSTRACT) && !pChildToken->IsSet(PROPERTY_BASEIMPLEMENTATION))
  1570. {
  1571. fOk = TRUE;
  1572. break;
  1573. }
  1574. } while (pChildToken = ChildList.GetNext());
  1575. if (fOk)
  1576. {
  1577. fprintf(fpHDLFile, "\nconst PROPERTYDESC * const %s::s_ppropdescsInVtblOrder%s[] = {\n", szClassName,
  1578. (LPSTR)pTearoff->GetTagValue(TEAROFF_INTERFACE));
  1579. for (j = i-1; j >= 0; j--)
  1580. {
  1581. pInterface = apInterface[j];
  1582. CTokenListWalker ChildLst(pInterface);
  1583. pChildToken = ChildLst.GetNext();
  1584. do
  1585. {
  1586. char szErrorText[MAX_LINE_LEN + 1];
  1587. Token *pExposeToken = NULL;
  1588. if (pChildToken->GetType() == TYPE_METHOD)
  1589. {
  1590. if (pChildToken->IsSet(METHOD_NOPROPDESC))
  1591. {
  1592. fNameOnly = _stricmp(pChildToken->GetTagValue(METHOD_NOPROPDESC), "nameonly") == 0;
  1593. pExposeToken = FindMatchingEntryWOPropDesc(pClassToken, pChildToken, fNameOnly);
  1594. if (!pExposeToken)
  1595. {
  1596. sprintf(szErrorText,
  1597. "Function member marked as nopropdesc can not find exact signature match in new interface:%s in Class:%s\n",
  1598. (LPCSTR)pChildToken->GetTagValue(METHOD_NAME),
  1599. szClassName);
  1600. ReportError(szErrorText);
  1601. return FALSE;
  1602. }
  1603. }
  1604. else
  1605. pExposeToken = pChildToken;
  1606. fprintf(fpHDLFile, " (PROPERTYDESC *)&s_methdesc%s%s,\n", pExposeToken->GetTagValue((int)METHOD_REFDTOCLASS), pExposeToken->GetTagValue(METHOD_NAME));
  1607. if (pPrimaryInterf == pInterface)
  1608. (*pNumVtblPropDescs)++;
  1609. }
  1610. else
  1611. {
  1612. if (pChildToken->IsSet(PROPERTY_SET) || pChildToken->IsSet(PROPERTY_GET))
  1613. {
  1614. BOOL fDoAgain = TRUE;
  1615. DoAgain:
  1616. if (pChildToken->IsSet(PROPERTY_NOPROPDESC))
  1617. {
  1618. fNameOnly = _stricmp(pChildToken->GetTagValue(PROPERTY_NOPROPDESC), "nameonly") == 0;
  1619. pExposeToken = FindMatchingEntryWOPropDesc(pClassToken, pChildToken, fNameOnly);
  1620. if (!pExposeToken)
  1621. {
  1622. sprintf(szErrorText,
  1623. "Function member marked as nopropdesc can not find exact signature match in new interface:%s in Class:%s\n",
  1624. (LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME),
  1625. szClassName);
  1626. ReportError(szErrorText);
  1627. return FALSE;
  1628. }
  1629. }
  1630. else
  1631. pExposeToken = pChildToken;
  1632. pExposeToken = pExposeToken ? pExposeToken : pChildToken;
  1633. fprintf(fpHDLFile, " (const PROPERTYDESC *)&s_propdesc%s%s,\n",
  1634. pExposeToken->GetTagValue((int)PROPERTY_REFDTOCLASS),
  1635. pExposeToken->GetTagValue(PROPERTY_NAME));
  1636. if (pPrimaryInterf == pInterface)
  1637. (*pNumVtblPropDescs)++;
  1638. // If property is getter and setter both then generate another propdesc (but just once).
  1639. if (fDoAgain && pChildToken->IsSet(PROPERTY_SET) && pChildToken->IsSet(PROPERTY_GET))
  1640. {
  1641. fDoAgain = FALSE;
  1642. goto DoAgain;
  1643. }
  1644. }
  1645. }
  1646. } while (pChildToken = ChildLst.GetNext());
  1647. }
  1648. fprintf(fpHDLFile, "};\n\n");
  1649. }
  1650. }
  1651. }
  1652. return TRUE;
  1653. }
  1654. BOOL CPDLParser::GenerateTearOffMethods (LPCSTR szClassName, Token *pTearoff, LPCSTR szInterfaceName, BOOL fMostDerived)
  1655. {
  1656. Token *pInterfaceToken;
  1657. Token *pChildToken;
  1658. char szText[MAX_LINE_LEN+1];
  1659. CTokenListWalker WholeList(pRuntimeList);
  1660. #if 0
  1661. if (strcmp(_pszPDLFileName, "div.pdl") == 0 || strcmp(szInterfaceName, "IHTMLDivElement") == 0)
  1662. __asm { int 3 };
  1663. #endif
  1664. // Find the interface decl
  1665. do
  1666. {
  1667. pInterfaceToken = WholeList.GetNext(TYPE_INTERFACE, szInterfaceName);
  1668. if (pInterfaceToken == NULL)
  1669. {
  1670. // if the deepest is IDispatch output that tearoff
  1671. if (_stricmp(szInterfaceName, "IDispatch"))
  1672. {
  1673. // but IUnknowns are OK so return true
  1674. if (_stricmp(szInterfaceName, "IUnknown"))
  1675. {
  1676. // its something we don't recognise so output error msg
  1677. sprintf(szText, "interface:%s unknown\n", (LPCSTR)szInterfaceName);
  1678. ReportError(szText);
  1679. return FALSE;
  1680. }
  1681. else
  1682. return TRUE;
  1683. }
  1684. else
  1685. {
  1686. return GenerateIDispatchTearoff(szClassName, pTearoff, szInterfaceName, fMostDerived);
  1687. }
  1688. }
  1689. } while (!pInterfaceToken->IsSet(INTERFACE_GUID));
  1690. // If we only want most derived then we're done otherwise continue recursing.
  1691. if (!fMostDerived)
  1692. {
  1693. // Generate the interfaces super tear off methods first
  1694. if (pInterfaceToken->IsSet(INTERFACE_SUPER))
  1695. {
  1696. GenerateTearOffMethods(szClassName, pTearoff, pInterfaceToken->GetTagValue(INTERFACE_SUPER));
  1697. }
  1698. }
  1699. else
  1700. {
  1701. // fMostDerived is only set for the primary interface, which we don't want stacked ontop of its
  1702. // derivations. so all we want to do is dump in the dispatch and go on.
  1703. GenerateIDispatchTearoff(szClassName, pTearoff, szInterfaceName, fMostDerived);
  1704. }
  1705. // generate the fn prototypes cast to generic fn pts in the
  1706. // tearoff table
  1707. CTokenListWalker ChildList(pInterfaceToken);
  1708. CString szProp;
  1709. Token *pArgToken;
  1710. fprintf ( fpHDLFile, " // %s methods\n", szInterfaceName);
  1711. while (pChildToken = ChildList.GetNext())
  1712. {
  1713. char szTemp[256];
  1714. char szTearOffClassName[256];
  1715. char szContextThunk[] = "ContextThunk_";
  1716. LPCSTR pCtxt;
  1717. if (pChildToken->GetType() == TYPE_METHOD)
  1718. {
  1719. CTokenListWalker ArgListWalker(pChildToken);
  1720. BOOL fFirstArg = TRUE;
  1721. char szTearoffMethod[128];
  1722. LPCSTR pMethodName;
  1723. pMethodName = pChildToken->IsSet(METHOD_SZINTERFACEEXPOSE) ?
  1724. (LPSTR)pChildToken->GetTagValue(METHOD_SZINTERFACEEXPOSE) :
  1725. (LPSTR)pChildToken->GetTagValue(METHOD_NAME);
  1726. FindTearoffMethod(pTearoff,
  1727. pMethodName,
  1728. szTearoffMethod);
  1729. strcpy(szTearOffClassName, szClassName);
  1730. GenerateWin16TearoffName(szTemp, szTearoffMethod, szTearOffClassName);
  1731. pCtxt = pChildToken->IsSet(METHOD_THUNKCONTEXT) ||
  1732. pChildToken->IsSet(METHOD_THUNKNODECONTEXT)
  1733. ? szContextThunk : "";
  1734. // Method
  1735. fprintf(fpHDLFile, " TEAROFF_METHOD(%s, %s%s, %s, (", szTearOffClassName, pCtxt, szTearoffMethod, szTemp);
  1736. // All automated methods MUST have an HRESULT for the return type.
  1737. if (_stricmp("HRESULT", (LPCSTR)pChildToken->GetTagValue(METHOD_RETURNTYPE)))
  1738. {
  1739. ReportError("Automated method must have HRESULT for return value\n");
  1740. return FALSE;
  1741. }
  1742. // Output each argument.
  1743. while (pArgToken = ArgListWalker.GetNext())
  1744. {
  1745. if (!fFirstArg)
  1746. fprintf(fpHDLFile, ",");
  1747. fprintf(fpHDLFile, "%s", ConvertType((LPCSTR)pArgToken->GetTagValue(METHODARG_TYPE)));
  1748. fFirstArg = FALSE;
  1749. }
  1750. fprintf(fpHDLFile, "))\n");
  1751. }
  1752. else
  1753. {
  1754. char szPropName[128];
  1755. char szTearoffMethod[128];
  1756. char szPropArgs[64];
  1757. LPCSTR pMethodName;
  1758. // Property
  1759. szProp = "";
  1760. pMethodName = pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
  1761. (LPSTR)pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
  1762. (LPSTR)pChildToken->GetTagValue(PROPERTY_NAME);
  1763. // Through the index/indextype & index1/indextype1 pdl tags
  1764. // you can provide up to two additional args for the property definition
  1765. pChildToken->AddParam(szProp, PROPERTY_INDEX, pChildToken->GetTagValue(PROPERTY_INDEXTYPE));
  1766. pChildToken->AddParam(szProp, PROPERTY_INDEX1, pChildToken->GetTagValue(PROPERTY_INDEXTYPE1));
  1767. if (szProp[0] != '\0')
  1768. szProp += ",";
  1769. pCtxt = pChildToken->IsSet(PROPERTY_THUNKCONTEXT) ||
  1770. pChildToken->IsSet(PROPERTY_THUNKNODECONTEXT)
  1771. ? szContextThunk : "";
  1772. if ( pChildToken->IsSet(PROPERTY_SET))
  1773. {
  1774. strcpy(szPropName, "put_");
  1775. strcat(szPropName, pMethodName);
  1776. if (FindTearoffMethod(pTearoff, szPropName, szTearoffMethod))
  1777. {
  1778. strcpy(szPropArgs, (LPCSTR)pChildToken->GetTagValue(PROPERTY_ATYPE));
  1779. strcpy(szTearOffClassName, szClassName);
  1780. }
  1781. else if (!FindTearoffProperty(pChildToken, szTearoffMethod, szTearOffClassName, szPropArgs, FALSE))
  1782. {
  1783. FindTearoffMethod(pTearoff, szPropName, szTearoffMethod);
  1784. strcpy(szPropArgs, (LPCSTR)pChildToken->GetTagValue(PROPERTY_ATYPE));
  1785. strcpy(szTearOffClassName, szClassName);
  1786. }
  1787. GenerateWin16TearoffName(szTemp, szTearoffMethod, szTearOffClassName);
  1788. fprintf(fpHDLFile, " TEAROFF_METHOD(%s, %s%s, %s, (%s%s)) // property set_%s\n",
  1789. szTearOffClassName,
  1790. pCtxt,
  1791. szTearoffMethod,
  1792. szTemp,
  1793. (LPCSTR)szProp,
  1794. (LPCSTR)szPropArgs,
  1795. (LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME));
  1796. }
  1797. if (pChildToken->IsSet(PROPERTY_GET))
  1798. {
  1799. strcpy(szPropName, "get_");
  1800. strcat(szPropName, pMethodName);
  1801. if (FindTearoffMethod(pTearoff, szPropName, szTearoffMethod))
  1802. {
  1803. strcpy(szPropArgs, (LPCSTR)pChildToken->GetTagValue(PROPERTY_ATYPE));
  1804. strcpy(szTearOffClassName, szClassName);
  1805. }
  1806. else if (!FindTearoffProperty(pChildToken, szTearoffMethod, szTearOffClassName, szPropArgs, TRUE))
  1807. {
  1808. FindTearoffMethod(pTearoff, szPropName, szTearoffMethod);
  1809. strcpy(szPropArgs, (LPCSTR)pChildToken->GetTagValue(PROPERTY_ATYPE));
  1810. strcpy(szTearOffClassName, szClassName);
  1811. }
  1812. GenerateWin16TearoffName(szTemp, szTearoffMethod, szTearOffClassName);
  1813. fprintf(fpHDLFile, " TEAROFF_METHOD(%s, %s%s, %s, (%s%s *)) // property get_%s\n",
  1814. szTearOffClassName,
  1815. pCtxt,
  1816. szTearoffMethod,
  1817. szTemp,
  1818. (LPCSTR)szProp,
  1819. (LPCSTR)szPropArgs,
  1820. (LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME));
  1821. }
  1822. }
  1823. }
  1824. return TRUE;
  1825. }
  1826. void CPDLParser::GenerateMethodImp ( Token *pClassToken,
  1827. Token *pChildToken, BOOL fIsSet, CString &szHandler,
  1828. CString &szHandlerArgs, CString &szOffsetOf, CString &szAType )
  1829. {
  1830. #if COLLECT_STATISTICS==1
  1831. // Collect statistics on total property code turds.
  1832. CollectStatistic(NUM_PROPTURDS, GetStatistic(NUM_PROPTURDS) + 1);
  1833. #endif
  1834. char *szHandlerMethodPrefix;
  1835. char *szAutomationMethodPrefix;
  1836. if ( fIsSet )
  1837. {
  1838. szHandlerMethodPrefix = "Set";
  1839. szAutomationMethodPrefix = "put_";
  1840. }
  1841. else
  1842. {
  1843. szHandlerMethodPrefix = "Get";
  1844. szAutomationMethodPrefix = "get_";
  1845. }
  1846. // Allow enums with an ATYPE of BSTR to be automated with the string handler
  1847. if ( szHandler == "Enum" && szAType == "BSTR" )
  1848. {
  1849. szHandler = "EnumString";
  1850. #if COLLECT_STATISTICS==1
  1851. // Collect statistics on number of enum code turds.
  1852. CollectStatistic(NUM_EMUMTURDS, GetStatistic(NUM_EMUMTURDS) + 1);
  1853. #endif
  1854. }
  1855. fprintf ( fpHDLFile,
  1856. "STDMETHODIMP %s::%s%s(%s%s)\n{\n",
  1857. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  1858. (LPCSTR)szAutomationMethodPrefix,
  1859. (LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ),
  1860. (LPCSTR)szAType,
  1861. fIsSet ? " v" : " * p" );
  1862. if ( pChildToken -> IsSet ( PROPERTY_PRECALLFUNCTION ) )
  1863. {
  1864. CString szfn;
  1865. szfn = pChildToken -> GetTagValue ( PROPERTY_PRECALLFUNCTION ) ;
  1866. // Give the super a chance to reject the call
  1867. fprintf ( fpHDLFile, " HRESULT hr;\n" );
  1868. if ( szfn == "super" )
  1869. {
  1870. fprintf ( fpHDLFile, " hr = super::%s%s(%s);\n",
  1871. szAutomationMethodPrefix,
  1872. (LPCSTR)pChildToken->GetTagValue ( PROPERTY_PRECALLFUNCTION ),
  1873. fIsSet ? "v" : "p" );
  1874. }
  1875. else
  1876. {
  1877. fprintf ( fpHDLFile, " hr = %s%s(%s);\n",
  1878. szAutomationMethodPrefix,
  1879. (LPCSTR)szfn,
  1880. fIsSet ? "v" : "p" );
  1881. }
  1882. fprintf ( fpHDLFile, " if ( hr )\n return hr;\n" );
  1883. }
  1884. if ( fIsSet && pChildToken -> IsSet ( PROPERTY_SETDESIGNMODE ) )
  1885. {
  1886. fprintf ( fpHDLFile, " if ( !IsDesignMode() )\n return SetErrorInfo(CTL_E_SETNOTSUPPORTEDATRUNTIME);\n" );
  1887. }
  1888. if ( szAType == "VARIANT" )
  1889. {
  1890. fprintf ( fpHDLFile, " return SetErrorInfo(s_propdesc%s%s.a.Handle%sProperty(%s, %s, this, CVOID_CAST%s));\n}\n",
  1891. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  1892. (LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ),
  1893. (LPCSTR)szHandler,
  1894. (LPCSTR)szHandlerArgs,
  1895. fIsSet ? "&v" : "p",
  1896. (LPCSTR)szOffsetOf );
  1897. }
  1898. else if ( pChildToken -> IsSet ( PROPERTY_SUBOBJECT ) )
  1899. {
  1900. fprintf ( fpHDLFile, " return %s::CreateSubObject ( GetElementPtr(), (PROPERTYDESC *)&s_propdesc%s%s,\n ",
  1901. (LPCSTR)pChildToken->GetTagValue ( PROPERTY_SUBOBJECT ),
  1902. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  1903. (LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ));
  1904. if ( pChildToken -> IsSet ( PROPERTY_PARAM1 ) )
  1905. {
  1906. fprintf ( fpHDLFile, "%s, ",
  1907. (LPCSTR)pChildToken->GetTagValue ( PROPERTY_PARAM1 ) );
  1908. }
  1909. fprintf ( fpHDLFile, "p );\n}\n" );
  1910. }
  1911. else
  1912. {
  1913. if ( szHandler == "Num" || szHandler == "Enum" )
  1914. {
  1915. fprintf ( fpHDLFile," return s_propdesc%s%s.b.%sNumberProperty(%s, this, CVOID_CAST%s);\n}\n",
  1916. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  1917. (LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ),
  1918. (LPCSTR)szHandlerMethodPrefix,
  1919. fIsSet ? "v" : "p",
  1920. (LPCSTR)szOffsetOf );
  1921. }
  1922. else
  1923. {
  1924. fprintf ( fpHDLFile, " return s_propdesc%s%s.b.%s%sProperty(%s, this, CVOID_CAST%s);\n}\n",
  1925. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  1926. (LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ),
  1927. (LPCSTR)szHandlerMethodPrefix,
  1928. (LPCSTR)szHandler,
  1929. fIsSet ? "v" : "p",
  1930. (LPCSTR)szOffsetOf );
  1931. }
  1932. }
  1933. }
  1934. void CPDLParser::GenerateCPPEnumDefs ( void )
  1935. {
  1936. Token *pToken;
  1937. char *pEValText;
  1938. // Only generate def's for this file
  1939. CTokenListWalker TokenList ( pRuntimeList, _pszPDLFileName );
  1940. fprintf ( fpHDLFile, "\n#ifndef _PROPDESCS_EXTERNAL\n\n" );
  1941. // Generate propdescs for every property token in every class ( in this file )
  1942. while ( pToken = TokenList.GetNext( TYPE_ENUM ) )
  1943. {
  1944. fprintf ( fpHDLFile, "EXTERN_C const ENUMDESC s_enumdesc%s = \n{ %u, %u, {\n",
  1945. pToken->GetTagValue ( ENUM_NAME ) ,
  1946. pToken->GetChildTokenCount(),
  1947. pToken->uEnumMask );
  1948. CTokenListWalker ChildList ( pToken );
  1949. while ( pToken = ChildList.GetNext() )
  1950. {
  1951. // If a string is specified use it
  1952. if ( pToken->IsSet ( EVAL_STRING ) )
  1953. {
  1954. pEValText = pToken->GetTagValue ( EVAL_STRING );
  1955. }
  1956. else
  1957. {
  1958. pEValText = pToken->GetTagValue ( EVAL_NAME );
  1959. }
  1960. fprintf ( fpHDLFile, " { _T(\"%s\"),%s},\n",
  1961. pEValText,
  1962. pToken->GetTagValue ( EVAL_VALUE ) );
  1963. }
  1964. fprintf ( fpHDLFile, "} };\n\n" );
  1965. }
  1966. fprintf ( fpHDLFile, "#endif // _PROPDESCS_EXTERNAL\n" );
  1967. }
  1968. void CPDLParser::GenerateInterfaceDISPIDs ( void )
  1969. {
  1970. Token *pInterfaceToken;
  1971. Token *pChildToken;
  1972. CString szName;
  1973. // Generate DISPID's for all interface methods that are not
  1974. // ref'd to a class
  1975. // Only generate def's for this file
  1976. CTokenListWalker TokenList ( pRuntimeList, _pszPDLFileName );
  1977. while ( pInterfaceToken = TokenList.GetNext( TYPE_INTERFACE ) )
  1978. {
  1979. szName = pInterfaceToken->GetTagValue ( INTERFACE_NAME );
  1980. if ( szName == "IDispatch" )
  1981. continue;
  1982. fprintf ( fpHDLFile, "// DISPIDs for class%s\n\n",
  1983. (LPCSTR)pInterfaceToken->GetTagValue ( INTERFACE_NAME ) );
  1984. CTokenListWalker ChildList ( pInterfaceToken );
  1985. while ( pChildToken = ChildList.GetNext() )
  1986. {
  1987. if ( pChildToken -> GetType() == TYPE_METHOD &&
  1988. !strlen( pChildToken -> GetTagValue ( METHOD_REFDTOCLASS ) ) &&
  1989. pChildToken -> IsSet ( METHOD_DISPID ) )
  1990. {
  1991. Token *pChildMatch = NULL;
  1992. CString szClassName;
  1993. Token *pClass;
  1994. szClassName = pInterfaceToken -> GetTagValue( METHOD_REFDTOCLASS );
  1995. pClass = FindClass ( szClassName );
  1996. if (pClass)
  1997. {
  1998. if (pChildToken->IsSet(METHOD_NOPROPDESC))
  1999. {
  2000. pChildMatch = FindMatchingEntryWOPropDesc(pClass, pChildToken);
  2001. }
  2002. }
  2003. if (!pChildMatch)
  2004. pChildMatch = pChildToken;
  2005. fprintf ( fpHDLFile, "#define DISPID_%s_%s %s\n",
  2006. (LPCSTR)pInterfaceToken->GetTagValue ( INTERFACE_NAME ),
  2007. (LPCSTR)pChildMatch->GetTagValue ( METHOD_NAME ),
  2008. (LPCSTR)pChildMatch->GetTagValue ( METHOD_DISPID ) );
  2009. }
  2010. }
  2011. }
  2012. }
  2013. void CPDLParser::GenerateEventDISPIDs ( FILE *fp, BOOL fPutDIID )
  2014. {
  2015. Token *pEventToken;
  2016. Token *pChildToken;
  2017. CString szName,szDISPName;
  2018. int i,nLength;
  2019. BOOL fPutComment;
  2020. // Generate DISPID's for all interface methods that are not
  2021. // ref'd to a class
  2022. // Only generate def's for this file
  2023. CTokenListWalker TokenList ( pRuntimeList, _pszPDLFileName );
  2024. while ( pEventToken = TokenList.GetNext( TYPE_EVENT ) )
  2025. {
  2026. szName = pEventToken->GetTagValue ( EVENT_NAME );
  2027. if ( szName == "IDispatch" || szName == "IUnknown" )
  2028. continue;
  2029. szName.ToUpper();
  2030. fPutComment = FALSE;
  2031. CTokenListWalker ChildList ( pEventToken );
  2032. while ( pChildToken = ChildList.GetNext() )
  2033. {
  2034. if ( pChildToken -> GetType() == TYPE_METHOD &&
  2035. !strlen( pChildToken -> GetTagValue ( METHOD_REFDTOCLASS ) ) &&
  2036. pChildToken -> IsSet ( METHOD_DISPID ) )
  2037. {
  2038. if ( !fPutComment )
  2039. {
  2040. fprintf ( fp, "// DISPIDs for event set %s\n\n",
  2041. (LPCSTR)pEventToken->GetTagValue ( EVENT_NAME ) );
  2042. fPutComment = TRUE;
  2043. }
  2044. szDISPName = pChildToken->GetTagValue ( METHOD_NAME );
  2045. szDISPName.ToUpper();
  2046. fprintf ( fp, "#define DISPID_%s_%s ",
  2047. (LPCSTR)szName,
  2048. (LPCSTR)szDISPName );
  2049. for ( i = 0, nLength = max ( 0, 49-szDISPName.Length()-szName.Length() ); i < nLength ; i++ )
  2050. {
  2051. fprintf ( fp, " " );
  2052. }
  2053. fprintf ( fp, "%s\n",
  2054. (LPCSTR)pChildToken->GetTagValue ( METHOD_DISPID ) );
  2055. }
  2056. }
  2057. if ( fPutDIID )
  2058. {
  2059. fprintf ( fp, "\nEXTERN_C const GUID DIID_%s;\n",
  2060. pEventToken->GetTagValue ( EVENT_NAME ));
  2061. }
  2062. if ( fPutComment )
  2063. fprintf ( fp, "\n" );
  2064. }
  2065. }
  2066. void CPDLParser::GenerateExternalInterfaceDISPIDs ( void )
  2067. {
  2068. Token *pInterfaceToken;
  2069. Token *pChildToken;
  2070. CString szName,szDISPName;
  2071. int i,nLength;
  2072. BOOL fPutComment;
  2073. // Generate DISPID's for all interface methods that are not
  2074. // ref'd to a class
  2075. // Only generate def's for this file
  2076. CTokenListWalker TokenList ( pRuntimeList, _pszPDLFileName );
  2077. while ( pInterfaceToken = TokenList.GetNext( TYPE_INTERFACE ) )
  2078. {
  2079. szName = pInterfaceToken->GetTagValue ( INTERFACE_NAME );
  2080. if ( szName == "IDispatch" || szName == "IUnknown" )
  2081. continue;
  2082. szName.ToUpper();
  2083. fPutComment = FALSE;
  2084. CTokenListWalker ChildList ( pInterfaceToken );
  2085. while ( pChildToken = ChildList.GetNext() )
  2086. {
  2087. Token *pChildMatch = NULL;
  2088. CString szClassName;
  2089. Token *pClass;
  2090. if ( !fPutComment )
  2091. {
  2092. fprintf ( fpDISPIDFile, "// DISPIDs for interface %s\n\n",
  2093. (LPCSTR)pInterfaceToken->GetTagValue ( INTERFACE_NAME ) );
  2094. fPutComment = TRUE;
  2095. }
  2096. if ( pChildToken -> GetType() == TYPE_METHOD )
  2097. {
  2098. szDISPName = pChildToken->GetTagValue ( METHOD_NAME );
  2099. szClassName = pChildToken -> GetTagValue( METHOD_REFDTOCLASS );
  2100. pClass = FindClass ( szClassName );
  2101. if (pClass)
  2102. {
  2103. if (pChildToken->IsSet(METHOD_NOPROPDESC))
  2104. {
  2105. if (pChildToken->IsSet(METHOD_SZINTERFACEEXPOSE))
  2106. szDISPName = pChildToken->GetTagValue(METHOD_SZINTERFACEEXPOSE);
  2107. pChildMatch = FindMatchingEntryWOPropDesc(pClass, pChildToken);
  2108. }
  2109. }
  2110. if (!pChildMatch)
  2111. pChildMatch = pChildToken;
  2112. }
  2113. else
  2114. {
  2115. // Property
  2116. szDISPName = pChildToken->GetTagValue ( PROPERTY_NAME );
  2117. szClassName = pChildToken -> GetTagValue( PROPERTY_REFDTOCLASS );
  2118. pClass = FindClass ( szClassName );
  2119. if (pClass)
  2120. {
  2121. if (pChildToken->IsSet(PROPERTY_NOPROPDESC))
  2122. {
  2123. if (pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE))
  2124. szDISPName = pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE);
  2125. pChildMatch = FindMatchingEntryWOPropDesc(pClass, pChildToken);
  2126. }
  2127. }
  2128. if (!pChildMatch)
  2129. pChildMatch = pChildToken;
  2130. }
  2131. szDISPName.ToUpper();
  2132. fprintf ( fpDISPIDFile, "#define DISPID_%s_%s ",
  2133. (LPCSTR)szName,
  2134. (LPCSTR)szDISPName );
  2135. for ( i = 0, nLength = max ( 0, 49-szDISPName.Length()-szName.Length() ); i < nLength ; i++ )
  2136. {
  2137. fprintf ( fpDISPIDFile, " " );
  2138. }
  2139. fprintf ( fpDISPIDFile, "%s\n",
  2140. (LPCSTR)pChildMatch->GetTagValue ( PROPERTY_DISPID ) );
  2141. }
  2142. if ( fPutComment )
  2143. fprintf ( fpDISPIDFile, "\n" );
  2144. }
  2145. }
  2146. void CPDLParser::GenerateClassDISPIDs ( void )
  2147. {
  2148. Token *pClassToken;
  2149. Token *pChildToken;
  2150. CString szCoClassName;
  2151. // Only generate def's for this file
  2152. CTokenListWalker TokenList ( pRuntimeList, _pszPDLFileName );
  2153. // Generate propdescs for every property token in every class ( in this file )
  2154. while ( pClassToken = TokenList.GetNext( TYPE_CLASS ) )
  2155. {
  2156. fprintf ( fpHDLFile, "// DISPIDs for class %s\n\n", (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ) );
  2157. if ( pClassToken -> IsSet ( CLASS_GUID ) )
  2158. {
  2159. pClassToken -> GetTagValueOrDefault ( szCoClassName,
  2160. CLASS_COCLASSNAME, pClassToken -> GetTagValue ( CLASS_NAME ) );
  2161. fprintf ( fpHDLFile, "EXTERN_C const GUID CLSID_%s;\n",
  2162. (LPCSTR)szCoClassName );
  2163. }
  2164. CTokenListWalker ChildList ( pClassToken );
  2165. while ( pChildToken = ChildList.GetNext() )
  2166. {
  2167. Token *pChildMatch = pChildToken;
  2168. if ( pChildMatch->nType == TYPE_PROPERTY && pChildMatch->IsSet ( PROPERTY_DISPID ) )
  2169. {
  2170. if (pChildMatch->IsSet(PROPERTY_NOPROPDESC))
  2171. {
  2172. pChildMatch = FindMatchingEntryWOPropDesc(pClassToken, pChildMatch);
  2173. if (!pChildMatch)
  2174. pChildMatch = pChildToken;
  2175. }
  2176. fprintf ( fpHDLFile, "#define DISPID_%s_%s %s\n",
  2177. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  2178. (LPCSTR)pChildMatch->GetTagValue ( PROPERTY_NAME ),
  2179. (LPCSTR)pChildMatch->GetTagValue ( PROPERTY_DISPID ) );
  2180. }
  2181. else if ( pChildMatch->nType == TYPE_METHOD && pChildMatch->IsSet ( METHOD_DISPID ) )
  2182. {
  2183. if (pChildMatch->IsSet(METHOD_NOPROPDESC))
  2184. {
  2185. pChildMatch = FindMatchingEntryWOPropDesc(pClassToken, pChildMatch);
  2186. if (!pChildMatch)
  2187. pChildMatch = pChildToken;
  2188. }
  2189. fprintf ( fpHDLFile, "#define DISPID_%s_%s %s\n",
  2190. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  2191. (LPCSTR)pChildMatch->GetTagValue ( METHOD_NAME ),
  2192. (LPCSTR)pChildMatch->GetTagValue ( METHOD_DISPID ) );
  2193. }
  2194. }
  2195. }
  2196. }
  2197. void CPDLParser::GeneratePropdescExtern ( Token *pClassToken, BOOL fRecurse )
  2198. {
  2199. Token *pChild;
  2200. Token *pSuperClassToken;
  2201. CTokenListWalker ChildList ( pClassToken );
  2202. // Add the supers definitions first. Recurse to the super of this super!!
  2203. // Notice that the fRecurse if used by abstract classes to only extern the
  2204. // PropertyDesc which are generated for the actual class.
  2205. pSuperClassToken = fRecurse ? GetSuperClassTokenPtr ( pClassToken ) : NULL;
  2206. if ( pSuperClassToken )
  2207. GeneratePropdescExtern ( pSuperClassToken );
  2208. // Don't generate any EXTERN_C for abstract class reference. The EXTERN_C
  2209. // is only in the hdl that contains both the PROPERTYDESC the EXTERN_C for
  2210. // the abstract class (e.g., bodyroot.hdl).
  2211. if ( fRecurse && pClassToken -> IsSet ( CLASS_ABSTRACT ) )
  2212. return;
  2213. fprintf ( fpHeaderFile, "\n#ifndef _%s_PROPDESCS_\n", pClassToken -> GetTagValue ( CLASS_NAME ) );
  2214. // Walk the super class propdescs looking for properties
  2215. while ( pChild = ChildList.GetNext() )
  2216. {
  2217. if ( pChild->GetType() == TYPE_PROPERTY )
  2218. {
  2219. StorageType stHowStored;
  2220. CString szHandler;
  2221. CString szFnPrefix;
  2222. szHandler = "";
  2223. szFnPrefix = "";
  2224. // Check for missing handler later
  2225. GetTypeDetails ( pChild->GetTagValue ( PROPERTY_TYPE ),
  2226. szHandler, szFnPrefix, &stHowStored );
  2227. if ( !ComputePROPDESC_STRUCT ( fpHeaderFile, pClassToken, pChild, szHandler, szFnPrefix ) )
  2228. return; // Bad error reported...leave
  2229. fprintf ( fpHeaderFile, " s_propdesc%s%s;\n",
  2230. pClassToken -> GetTagValue ( CLASS_NAME ),
  2231. pChild -> GetTagValue ( PROPERTY_NAME ) );
  2232. }
  2233. else if ( pChild->GetType() == TYPE_METHOD )
  2234. {
  2235. fprintf ( fpHeaderFile, "EXTERN_C const PROPERTYDESC_METHOD s_methdesc%s%s;\n",
  2236. pClassToken -> GetTagValue ( CLASS_NAME ),
  2237. pChild -> GetTagValue ( METHOD_NAME ) );
  2238. }
  2239. }
  2240. fprintf ( fpHeaderFile, "\n#endif\n" );
  2241. }
  2242. BOOL CPDLParser::GeneratePropdescReference ( Token *pClassToken,
  2243. BOOL fDerivedClass,
  2244. PropdescInfo *pPI,
  2245. int *pnPI,
  2246. BOOL &bHookToCElement,
  2247. int *pnSharedEntries )
  2248. {
  2249. Token *pChild;
  2250. if (!pClassToken)
  2251. return TRUE;
  2252. CTokenListWalker ChildList ( pClassToken );
  2253. // If the class superclass if CElement, we want to hook to CElement's hash table
  2254. // If this is not the case, we want to do what we used to do and repeat
  2255. // the super class properties in the subclasses.
  2256. if(GetSuperClassTokenPtr ( pClassToken ) &&
  2257. (strcmp(GetSuperClassTokenPtr ( pClassToken ) ->GetTagValue ( CLASS_NAME ),
  2258. "CElement") == 0))
  2259. {
  2260. bHookToCElement = TRUE;
  2261. }
  2262. if ( !GeneratePropdescReference ( GetSuperClassTokenPtr ( pClassToken ),
  2263. FALSE, pPI, pnPI,
  2264. bHookToCElement, pnSharedEntries ) )
  2265. {
  2266. return FALSE;
  2267. }
  2268. if (fDerivedClass)
  2269. {
  2270. ChildList.Reset();
  2271. }
  2272. // Walk the super class propdescs looking for properties
  2273. while ( pChild = ChildList.GetNext() )
  2274. {
  2275. if ( pChild->GetType() == TYPE_PROPERTY )
  2276. {
  2277. if ( !pChild->IsSet ( PROPERTY_INTERNAL ) && !pChild->IsSet ( PROPERTY_ABSTRACT ) &&
  2278. !pChild->IsSet( PROPERTY_NOPROPDESC ) &&
  2279. (!pChild->IsSet ( PROPERTY_NOPERSIST ) ||
  2280. ( pChild->IsSet ( PROPERTY_NOPERSIST ) && pClassToken->IsSet( CLASS_KEEPNOPERSIST ) ) ) )
  2281. {
  2282. if(bHookToCElement && (strcmp(pClassToken -> GetTagValue ( CLASS_NAME ), "CElement") == 0))
  2283. {
  2284. *pnSharedEntries += 1;
  2285. }
  2286. else
  2287. {
  2288. pPI[*pnPI].Set(pClassToken -> GetTagValue ( CLASS_NAME ),
  2289. pChild -> GetTagValue ( PROPERTY_NAME ) ,
  2290. fDerivedClass,
  2291. pChild->GetTagValue ( PROPERTY_SZATTRIBUTE ),
  2292. PDLPARSE_BELONGSTOPARSE);
  2293. *pnPI += 1;
  2294. }
  2295. }
  2296. }
  2297. }
  2298. return TRUE;
  2299. }
  2300. BOOL CPDLParser::GenerateCPC ( Token *pThisClassToken)
  2301. {
  2302. if ( IsUniqueCPC ( pThisClassToken ) )
  2303. {
  2304. fprintf ( fpHDLFile, "\nconst CONNECTION_POINT_INFO %s::s_acpi[] = {\n",
  2305. pThisClassToken -> GetTagValue ( CLASS_NAME ) );
  2306. fprintf ( fpHDLFile, " CPI_ENTRY(IID_IPropertyNotifySink, DISPID_A_PROPNOTIFYSINK)\n" );
  2307. fprintf ( fpHDLFile, " CPI_ENTRY(DIID_%s, DISPID_A_EVENTSINK)\n",
  2308. pThisClassToken->GetTagValue( CLASS_EVENTS ) );
  2309. if (pThisClassToken->IsSet(CLASS_NONPRIMARYEVENTS1))
  2310. {
  2311. fprintf(fpHDLFile, " CPI_ENTRY(DIID_%s, DISPID_A_EVENTSINK)\n",
  2312. pThisClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS1));
  2313. }
  2314. if (pThisClassToken->IsSet(CLASS_NONPRIMARYEVENTS2))
  2315. {
  2316. fprintf(fpHDLFile, " CPI_ENTRY(DIID_%s, DISPID_A_EVENTSINK)\n",
  2317. pThisClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS2));
  2318. }
  2319. if (pThisClassToken->IsSet(CLASS_NONPRIMARYEVENTS3))
  2320. {
  2321. fprintf(fpHDLFile, " CPI_ENTRY(DIID_%s, DISPID_A_EVENTSINK)\n",
  2322. pThisClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS3));
  2323. }
  2324. if (pThisClassToken->IsSet(CLASS_NONPRIMARYEVENTS4))
  2325. {
  2326. fprintf(fpHDLFile, " CPI_ENTRY(DIID_%s, DISPID_A_EVENTSINK)\n",
  2327. pThisClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS4));
  2328. }
  2329. fprintf ( fpHDLFile, " CPI_ENTRY(IID_ITridentEventSink, DISPID_A_EVENTSINK)\n" );
  2330. fprintf ( fpHDLFile, " CPI_ENTRY(IID_IDispatch, DISPID_A_EVENTSINK)\n" );
  2331. fprintf ( fpHDLFile, " CPI_ENTRY_NULL\n};\n" );
  2332. }
  2333. return TRUE;
  2334. }
  2335. #ifdef COMPLUS_SHIM
  2336. void
  2337. CPDLParser::GenComPlusInheritance (Token *pClass, CString & inheritanceCStr)
  2338. {
  2339. // Any other interface to expose in the coclass which is part of the primary
  2340. // interface?
  2341. CString primaryInterfCStr;
  2342. CTokenListWalker ChildWalker(pClass);
  2343. Token *pChildToken;
  2344. BOOL fFirstInterf;
  2345. // Get the primary interface, if one exists.
  2346. if (pClass->IsSet(CLASS_INTERFACE))
  2347. {
  2348. primaryInterfCStr = pClass->GetTagValue(CLASS_INTERFACE);
  2349. inheritanceCStr = "public ICOMCookie, public ";
  2350. inheritanceCStr += primaryInterfCStr;
  2351. inheritanceCStr += "COMPLUS";
  2352. fFirstInterf = FALSE;
  2353. }
  2354. else
  2355. {
  2356. inheritanceCStr = "";
  2357. fFirstInterf = TRUE;
  2358. }
  2359. while (pChildToken = ChildWalker.GetNext())
  2360. {
  2361. if (pChildToken->GetType() == TYPE_IMPLEMENTS)
  2362. {
  2363. Token *pInterf;
  2364. CString szInterface;
  2365. szInterface = pChildToken->GetTagValue(IMPLEMENTS_NAME);
  2366. pInterf = FindInterface(szInterface);
  2367. if (pInterf)
  2368. {
  2369. // Is the interface a local one if not then don't check, we
  2370. // only need to check where interfaces are actually used.
  2371. if (FindInterfaceLocally(szInterface))
  2372. {
  2373. // If the super isn't specified and it's not a primary interface
  2374. // then error the super is required for non-primary interfaces.
  2375. if (_stricmp((LPSTR)pClass->GetTagValue(CLASS_INTERFACE),
  2376. (LPSTR)pInterf->GetTagValue(INTERFACE_NAME)) &&
  2377. !pInterf->IsSet(INTERFACE_SUPER) &&
  2378. !IsPrimaryInterface(szInterface))
  2379. {
  2380. char szErrorText [ MAX_LINE_LEN+1 ];
  2381. sprintf(szErrorText, "Interface %s missing super key.\n",
  2382. (LPSTR)pInterf->GetTagValue(INTERFACE_NAME));
  2383. ReportError(szErrorText);
  2384. return;
  2385. }
  2386. }
  2387. // If an implements is a primary interface then don't inherit again we did that at the beginning.
  2388. if (primaryInterfCStr != szInterface)
  2389. {
  2390. if (fFirstInterf)
  2391. {
  2392. fFirstInterf = FALSE;
  2393. }
  2394. else
  2395. {
  2396. inheritanceCStr += ",";
  2397. }
  2398. inheritanceCStr += " public ";
  2399. inheritanceCStr += pInterf->GetTagValue(INTERFACE_NAME);
  2400. inheritanceCStr += "COMPLUS";
  2401. }
  2402. }
  2403. }
  2404. }
  2405. }
  2406. #endif // COMPLUS_SHIM
  2407. void
  2408. CPDLParser::GenerateVTableArray (Token *pThisClassToken, BOOL *pbHashTableExists )
  2409. {
  2410. Token *pDerivedClass;
  2411. PropdescInfo rgPI[400]; // Max. number of method/prop for interface.
  2412. int nPI = 0;
  2413. UINT uVTblIndex = 0;
  2414. CString szInterf;
  2415. Token *pInterf;
  2416. BOOL bHookToCElement = FALSE;
  2417. int nSharedEntries = 0;
  2418. *pbHashTableExists = FALSE;
  2419. // Abstract classes don't need the vtable unless they name is CElement
  2420. // TODO: Terry, Implement the shared keywork here.
  2421. if ( (pThisClassToken->IsSet ( CLASS_ABSTRACT )) &&
  2422. (_stricmp(pThisClassToken->GetTagValue(CLASS_NAME), "CElement") != 0))
  2423. return;
  2424. pDerivedClass = pThisClassToken;
  2425. GetInterf:
  2426. szInterf = pDerivedClass->GetTagValue(CLASS_INTERFACE);
  2427. // If no interface then use the super to find an interface.
  2428. if (!szInterf.Length())
  2429. {
  2430. CString szClass;
  2431. szClass = pDerivedClass -> GetTagValue ( CLASS_SUPER );
  2432. pDerivedClass = FindClass(szClass);
  2433. if (!pDerivedClass)
  2434. ReportError ( "Unknown class\n" );
  2435. goto GetInterf;
  2436. }
  2437. pInterf = FindInterface(szInterf);
  2438. if (pInterf || strcmp((LPCSTR)szInterf, "IDispatch") == 0)
  2439. {
  2440. #ifdef COMPLUS_SHIM
  2441. // ***TLL*** COM+: Not spitting COM+ proxies for internal.pdl and mshtmext.pdl need to do, shouldn't special case.
  2442. BOOL fInternalPDL = (_stricmp(_pszPDLFileName, "internal.pdl") == 0) || (_stricmp(_pszPDLFileName, "mshtmext.pdl") == 0);
  2443. // Do we have a real coclass w/ a real GUID?
  2444. if (pThisClassToken->IsSet(CLASS_GUID) &&
  2445. pThisClassToken->IsSet(CLASS_INTERFACE) && !fInternalPDL)
  2446. {
  2447. // Then let's do some COM+ work...
  2448. CString inheritDecl;
  2449. CString szClassName;
  2450. if (pThisClassToken->IsSet(CLASS_COCLASSNAME))
  2451. szClassName = pThisClassToken->GetTagValue(CLASS_COCLASSNAME);
  2452. else
  2453. szClassName = pThisClassToken->GetTagValue(CLASS_NAME);
  2454. // Window needs some special processing as this is how unmanaged code hooks to
  2455. // managed code.
  2456. if (szClassName == "HTMLWindow2")
  2457. {
  2458. fprintf(fpHComPlusFile, "[managed, com, uuid={FF6BF9BB-FF1B-348D-8C21-CE642A866E7F}] __interface ICOMPLUSHookWindow\n");
  2459. fprintf(fpHComPlusFile, "{\n");
  2460. fprintf(fpHComPlusFile, "public:\n");
  2461. fprintf(fpHComPlusFile, "\tvoid Init(unsigned int myThis);\n");
  2462. fprintf(fpHComPlusFile, "};\n\n");
  2463. }
  2464. // COM+ managed code:
  2465. fprintf(fpHComPlusFile, "[managed, coclass");
  2466. if (szClassName == "HTMLWindow2")
  2467. {
  2468. fprintf(fpHComPlusFile, " , uuid={D66BF9BF-FF1B-348D-8C21-CE642A866E7F}");
  2469. }
  2470. fprintf(fpHComPlusFile, "] class %sCOMPLUS", (LPCSTR)szClassName);
  2471. GenComPlusInheritance(pThisClassToken, inheritDecl);
  2472. if (inheritDecl.Length())
  2473. {
  2474. fprintf(fpHComPlusFile, " : %s", (LPCSTR)inheritDecl);
  2475. if (szClassName == "HTMLWindow2")
  2476. {
  2477. fprintf(fpHComPlusFile, ", private ICOMPLUSHookWindow");
  2478. }
  2479. fprintf(fpHComPlusFile, "\n{\n");
  2480. }
  2481. else
  2482. {
  2483. fprintf(fpHComPlusFile, "\n{\n");
  2484. }
  2485. fprintf(fpHComPlusFile, "private:\n");
  2486. fprintf(fpHComPlusFile, "\tunsigned int\t_myThis;\n\n");
  2487. fprintf(fpHComPlusFile, "public:\n");
  2488. fprintf(fpHComPlusFile, "\t%sCOMPLUS (unsigned int myThis)\n\t\t{ _myThis = myThis; }\n\n", (LPCSTR)szClassName);
  2489. fprintf(fpHComPlusFile, "\tunsigned int getCOMCookie()\n\t\t{ return _myThis; }\n\n");
  2490. if (szClassName == "HTMLWindow2")
  2491. {
  2492. fprintf(fpHComPlusFile, "\tHTMLWindow2COMPLUS ()\n");
  2493. fprintf(fpHComPlusFile, "\t\t{ _myThis = 0; }\n\n");
  2494. fprintf(fpHComPlusFile, "\tvoid Init(unsigned int myThis)\n\t\t{ _myThis = myThis; }\n\n");
  2495. }
  2496. }
  2497. #endif // COMPLUS_SHIM
  2498. CVTableHash VTableHash; // Special hashtable that aids in spitting out the hash table
  2499. // Add the parser properties to the PropdescInfo array
  2500. if(!GeneratePropdescReference(pThisClassToken, TRUE, rgPI, &nPI, bHookToCElement, &nSharedEntries ))
  2501. ReportError("Error Storing PropDescs in PROPDESC array in HashTable");
  2502. // Add the OM properties and methods to the PropdescInfo array
  2503. if (pInterf)
  2504. {
  2505. ComputeVTable( pThisClassToken,
  2506. pInterf,
  2507. FALSE,
  2508. rgPI,
  2509. &nPI,
  2510. &uVTblIndex,
  2511. &VTableHash,
  2512. bHookToCElement);
  2513. }
  2514. #ifdef COMPLUS_SHIM
  2515. if (pThisClassToken->IsSet(CLASS_GUID) &&
  2516. pThisClassToken->IsSet(CLASS_INTERFACE) && !fInternalPDL)
  2517. {
  2518. fprintf(fpHComPlusFile, "};\n\n\n");
  2519. }
  2520. #endif // COMPLUS_SHIM
  2521. // Number of entries in vtable array.
  2522. *pbHashTableExists = bHookToCElement || (nPI > 0);
  2523. // Write out the "style" mini-propdesc array if we are dealing with
  2524. // the element class. The reason we do this is because a parser and OM
  2525. // propdesc (both of which are different) resolve to the same entry in
  2526. // the hash table. Hence, we have to make a hack and have the name resolve
  2527. // to an array of propdescs.
  2528. if(strcmp(pThisClassToken->GetTagValue(CLASS_NAME), "CElement") == 0)
  2529. {
  2530. fprintf(fpHDLFile, "static const PROPERTYDESC *s_propdescCElementStyleArray [ ] = \n"
  2531. "{\n"
  2532. " (PROPERTYDESC *)&s_propdescCElementstyle,\n"
  2533. " (PROPERTYDESC *)&s_propdescCElementstyle_Str\n"
  2534. "};\n");
  2535. }
  2536. else if(strcmp(pThisClassToken->GetTagValue(CLASS_NAME), "CInput") == 0)
  2537. {
  2538. fprintf(fpHDLFile, "static const PROPERTYDESC *s_propdescCInputCheckedArray [ ] = \n"
  2539. "{\n"
  2540. " (PROPERTYDESC *)&s_propdescCInputchecked,\n"
  2541. " (PROPERTYDESC *)&s_propdescCInputdefaultChecked\n"
  2542. "};\n");
  2543. }
  2544. // Write out the hash table
  2545. // Convert the class to a Unicode string so that it works correctly
  2546. // with the hash table, which is Unicode.
  2547. WCHAR strUnicode[256];
  2548. int retVal =
  2549. MultiByteToWideChar(CP_ACP, 0, pThisClassToken->GetTagValue(CLASS_NAME),
  2550. 256,
  2551. strUnicode, 256);
  2552. if(retVal == 0)
  2553. {
  2554. ReportError("Error: Unable to convert classname to a Unicode string");
  2555. return;
  2556. }
  2557. if(VTableHash.GetHashTableLength() > 1024)
  2558. {
  2559. ReportError("Error: Hash table size has grown beyond 10K. Find more bits!");
  2560. return;
  2561. }
  2562. if(VTableHash.ToFile(fpHDLFile,
  2563. strUnicode,
  2564. nSharedEntries) != S_OK)
  2565. {
  2566. ReportError("Error: Unable to write out hashtable");
  2567. return;
  2568. }
  2569. // Write out the Hash Table Aggregate
  2570. fprintf(fpHDLFile,
  2571. "const CPtrBagVTableAggregate %s::s_StringTableAggregate = {\n"
  2572. " {\n", pThisClassToken->GetTagValue(CLASS_NAME));
  2573. if(bHookToCElement)
  2574. fprintf(fpHDLFile, " (CPtrBagVTable *)&CElement::s_StringTable,\n");
  2575. // Every class aggregates to itself.
  2576. fprintf(fpHDLFile,
  2577. " (CPtrBagVTable *)&%s::s_StringTable,\n"
  2578. " NULL\n"
  2579. " }\n"
  2580. "};\n", pThisClassToken->GetTagValue(CLASS_NAME));
  2581. // Store away a special cache for the document
  2582. if(_stricmp(pThisClassToken->GetTagValue(CLASS_NAME), "COmWindowProxy") == 0)
  2583. {
  2584. DWORD index;
  2585. if(!VTableHash.GetIndex(_T("document"), &index))
  2586. {
  2587. ReportError("The document must exist in the COmWindowProxy");
  2588. return;
  2589. }
  2590. fprintf(fpHDLFile, "const VTABLEDESC * const COmWindowProxy::s_COmWindowProxyDocument = &s_AssocVTableCOmWindowProxy%d._VTableDesc;\n", index);
  2591. }
  2592. }
  2593. else
  2594. {
  2595. char szErrorText [ MAX_LINE_LEN+1 ];
  2596. sprintf( szErrorText, "Unknown interface %s\n", (LPCSTR) szInterf );
  2597. ReportError ( szErrorText );
  2598. }
  2599. }
  2600. void
  2601. CPDLParser::SortPropDescInfo (PropdescInfo *pPI, int cPDI)
  2602. {
  2603. int x, y, cc;
  2604. PropdescInfo pd;
  2605. //sort em
  2606. for (x = 0; x < cPDI - 1; ++x)
  2607. {
  2608. for (y = x; y < cPDI; ++y)
  2609. {
  2610. cc = _stricmp( pPI[x]._szSortKey, pPI[y]._szSortKey ); // API caveat
  2611. if (cc > 0)
  2612. {
  2613. memcpy(&pd, pPI + x, sizeof(pd));
  2614. memcpy(pPI + x, pPI + y, sizeof(pd));
  2615. memcpy(pPI + y, &pd, sizeof(pd));
  2616. }
  2617. }
  2618. }
  2619. }
  2620. BOOL
  2621. CPDLParser::ComputeVTable ( Token *pClass,
  2622. Token *pInterface,
  2623. BOOL fDerived,
  2624. PropdescInfo *pPI,
  2625. int *piPI,
  2626. UINT *pUVTblIdx,
  2627. CVTableHash *pVTableHash,
  2628. BOOL &bHookToCElement,
  2629. BOOL fNonPrimaryTearoff/*= FALSE*/ )
  2630. {
  2631. CString szSuperInterf;
  2632. Token *pChildToken;
  2633. int cFuncs = 0;
  2634. BOOL fProperty = FALSE;
  2635. int idxIIDPrimaryTearoff = -1;
  2636. int idxIID;
  2637. CString szInterface;
  2638. // Compute if this interface on the class is a primary interface tearoff.
  2639. if (!fNonPrimaryTearoff)
  2640. {
  2641. Token *pTearoff;
  2642. pTearoff = FindTearoff(pClass->GetTagValue(CLASS_NAME), pInterface->GetTagValue(INTERFACE_NAME));
  2643. if (pTearoff)
  2644. {
  2645. CString szInterface;
  2646. Token *pInterfaceToken;
  2647. szInterface = pTearoff->GetTagValue(TEAROFF_INTERFACE);
  2648. pInterfaceToken = FindInterface(szInterface);
  2649. // If primary interface is not derived from IDispatch then this
  2650. // interface and all derived interfaces (vtable layout) are separated
  2651. // not concatenated.
  2652. LPSTR szSuperPrimaryInterf = pInterfaceToken->GetTagValue(INTERFACE_SUPER);
  2653. if (szSuperPrimaryInterf && *szSuperPrimaryInterf)
  2654. fNonPrimaryTearoff = ((_stricmp(szSuperPrimaryInterf, "IDispatch") ||
  2655. (_stricmp(pClass->GetTagValue(CLASS_NAME), "CElement") == 0)));
  2656. else
  2657. {
  2658. fNonPrimaryTearoff = FALSE;
  2659. }
  2660. }
  2661. }
  2662. szInterface = pInterface->GetTagValue(INTERFACE_NAME);
  2663. // We want classes which have their primary interface IHTMLElement
  2664. // and are derived from CElement to hook to CElement
  2665. if((szInterface == "IHTMLElement") &&
  2666. (_stricmp(pClass->GetTagValue(CLASS_NAME), "CElement") != 0))
  2667. {
  2668. bHookToCElement = TRUE;
  2669. }
  2670. else
  2671. {
  2672. idxIID = FindAndAddIIDs(szInterface);
  2673. if (idxIID == -1)
  2674. {
  2675. ReportError("Problem with IID adding.\n");
  2676. return FALSE;
  2677. }
  2678. if (fNonPrimaryTearoff)
  2679. idxIIDPrimaryTearoff = idxIID;
  2680. szSuperInterf = pInterface->GetTagValue(INTERFACE_SUPER);
  2681. if (szSuperInterf && *szSuperInterf && szSuperInterf != "IDispatch")
  2682. {
  2683. Token *pSuperInterf;
  2684. pSuperInterf = FindInterface(szSuperInterf);
  2685. if (!pSuperInterf)
  2686. return FALSE;
  2687. if (!ComputeVTable(pClass,
  2688. pSuperInterf,
  2689. TRUE,
  2690. pPI,
  2691. piPI,
  2692. pUVTblIdx,
  2693. pVTableHash,
  2694. bHookToCElement,
  2695. fNonPrimaryTearoff))
  2696. return FALSE;
  2697. }
  2698. CTokenListWalker ChildList ( pInterface );
  2699. while ( pChildToken = ChildList.GetNext() )
  2700. {
  2701. UINT uIIDnVTbl;
  2702. cFuncs = 0;
  2703. if ( pChildToken -> GetType() == TYPE_PROPERTY )
  2704. {
  2705. fProperty = TRUE;
  2706. cFuncs = pChildToken -> IsSet ( PROPERTY_GET ) ? 1 : 0;
  2707. cFuncs += (pChildToken -> IsSet ( PROPERTY_SET ) ? 1 : 0);
  2708. if (pChildToken->IsSet(PROPERTY_NOPROPDESC))
  2709. goto AddInVTable;
  2710. }
  2711. else if ( pChildToken -> GetType() == TYPE_METHOD )
  2712. {
  2713. fProperty = FALSE;
  2714. cFuncs = 1;
  2715. if (pChildToken->IsSet(METHOD_NOPROPDESC))
  2716. goto AddInVTable;
  2717. }
  2718. else
  2719. {
  2720. ReportError ( "Unknown token type in ComputeVTable.\n" );
  2721. return FALSE;
  2722. }
  2723. // Compute vtable offset. If primary interface is a tearoff then set
  2724. // the offset and the idx into the IID table. Note, all indexes start
  2725. // at 1 (zero is reserved to imply classdesc primary interface).
  2726. uIIDnVTbl = fNonPrimaryTearoff ? (((idxIIDPrimaryTearoff + 1) << 8) | *pUVTblIdx) : *pUVTblIdx;
  2727. pPI[*piPI].SetVTable(pChildToken -> GetTagValue ( fProperty ? (int)PROPERTY_REFDTOCLASS : (int)METHOD_REFDTOCLASS ),
  2728. pChildToken -> GetTagValue ( fProperty ? (int)PROPERTY_NAME : (int)METHOD_NAME ),
  2729. FALSE, // Unused.
  2730. pChildToken -> GetTagValue ( PROPERTY_SZATTRIBUTE ),
  2731. uIIDnVTbl | PDLPARSE_BELONGSTOOM, // Computed IID/VTable where iidIdx might be zero for the primary interface.
  2732. fProperty,
  2733. idxIID, // Index of interface
  2734. pChildToken);
  2735. (*piPI)++;
  2736. AddInVTable:
  2737. (*pUVTblIdx) += cFuncs;
  2738. }
  2739. }
  2740. // Each derived interface of the primary tearoff is separated not a straight
  2741. // derivation.
  2742. if (fNonPrimaryTearoff && _stricmp(szInterface, "IHTMLDocument"))
  2743. *pUVTblIdx = 0;
  2744. // Top most interface?
  2745. if ( !fDerived )
  2746. {
  2747. // Now check for any other interfaces mentioned in the as implements in
  2748. // the class it is exposed in the coclass, that interface is a
  2749. // separately supported interface.
  2750. CTokenListWalker ChildWalker(pClass);
  2751. Token *pChildToken;
  2752. CString szInterface;
  2753. Token *pInterfToken;
  2754. while (pChildToken = ChildWalker.GetNext())
  2755. {
  2756. if (pChildToken->GetType() == TYPE_IMPLEMENTS)
  2757. {
  2758. *pUVTblIdx = 0; // implements always starts at 0 vtable offset.
  2759. szInterface = pChildToken->GetTagValue(IMPLEMENTS_NAME);
  2760. if(_stricmp(pInterface->GetTagValue(INTERFACE_NAME), szInterface) == 0)
  2761. continue;
  2762. // TODO: TerryLu - Need to add code here to recongize and handle
  2763. // shares. Currently, we hardcode the following interfaces
  2764. // as once which are shared and implemented by CElement directly
  2765. if (szInterface == "IHTMLElement6")
  2766. {
  2767. ReportError ( "Need to Add IHTMLElement6 in parser.cxx(ComputeVTable())" );
  2768. return FALSE;
  2769. }
  2770. if ( ((szInterface == "IHTMLElement") ||
  2771. (szInterface == "IHTMLElement2") ||
  2772. (szInterface == "IHTMLElement3") ||
  2773. (szInterface == "IHTMLElement4") ||
  2774. (szInterface == "IHTMLElement5") ) &&
  2775. ((_stricmp(pClass->GetTagValue(CLASS_NAME), "CElement") != 0)) )
  2776. {
  2777. bHookToCElement = TRUE;
  2778. continue;
  2779. }
  2780. pInterfToken = FindInterface(szInterface);
  2781. if (pInterfToken)
  2782. {
  2783. if (!ComputeVTable(pClass,
  2784. pInterfToken,
  2785. TRUE,
  2786. pPI,
  2787. piPI,
  2788. pUVTblIdx,
  2789. pVTableHash,
  2790. bHookToCElement,
  2791. TRUE))
  2792. return FALSE;
  2793. }
  2794. }
  2795. }
  2796. // Output the vtable interface sorted by name.
  2797. for (int iVTbl = 0; iVTbl < *piPI; iVTbl++)
  2798. {
  2799. PropdescInfo *pPrevPropdescInfo;
  2800. // Convert the sort key to unicode since the HashTable is in Unicode
  2801. WCHAR strUnicode[256];
  2802. int retVal =
  2803. MultiByteToWideChar(CP_ACP, 0, pPI[iVTbl]._szSortKey,
  2804. 256,
  2805. strUnicode, 256);
  2806. if(retVal == 0)
  2807. {
  2808. ReportError("Unable to convert class name to Unicode");
  2809. return FALSE;
  2810. }
  2811. // Change the style property to point to a special array
  2812. // of PropertyDescs if we are dealing with the CElement class
  2813. if((_stricmp(pPI[iVTbl]._szSortKey, "style") == 0) &&
  2814. (_stricmp(pClass->GetTagValue(CLASS_NAME), "CElement") == 0))
  2815. {
  2816. pPI[iVTbl]._szPropName = "StyleArray";
  2817. pPI[iVTbl]._uVTblIndex |= PDLPARSE_PROPDESCARRAY;
  2818. pPI[iVTbl]._uVTblIndex |= PDLPARSE_BELONGSTOBOTH;
  2819. }
  2820. else if((_stricmp(pPI[iVTbl]._szSortKey, "checked") == 0) &&
  2821. (_stricmp(pClass->GetTagValue(CLASS_NAME), "CInput") == 0))
  2822. // Change the checked property to point to a special array
  2823. // of PropertyDescs if we are dealing with the CInput class
  2824. {
  2825. pPI[iVTbl]._szPropName = "CheckedArray";
  2826. pPI[iVTbl]._uVTblIndex |= PDLPARSE_PROPDESCARRAY;
  2827. pPI[iVTbl]._uVTblIndex |= PDLPARSE_BELONGSTOBOTH;
  2828. }
  2829. // If the hash table entry was already set by the parser,
  2830. // make it a shared entry by the parser and OM.
  2831. pPrevPropdescInfo = (PropdescInfo *)pVTableHash->GetCi(strUnicode);
  2832. if(pPrevPropdescInfo)
  2833. {
  2834. // We cannot have two different properties map to the same name
  2835. // unless they are ones we already know about
  2836. if((_stricmp(pPrevPropdescInfo->_szPropName, pPI[iVTbl]._szPropName) != 0) &&
  2837. (_stricmp(pPI[iVTbl]._szSortKey, "checked") != 0) &&
  2838. (_stricmp(pPI[iVTbl]._szSortKey, "style") != 0))
  2839. {
  2840. ReportError("We cannot have two different properties map to the same name");
  2841. return FALSE;
  2842. }
  2843. pPI[iVTbl]._uVTblIndex |= PDLPARSE_BELONGSTOBOTH;
  2844. }
  2845. // Set the entry in the hash table
  2846. if(pVTableHash->SetCi(strUnicode,
  2847. &pPI[iVTbl]) != S_OK)
  2848. {
  2849. ReportError("Error: Unable to add Hash entry to table");
  2850. return FALSE;
  2851. }
  2852. #ifdef COMPLUS_SHIM
  2853. // ***TLL*** COM+: Not spitting COM+ proxies for internal.pdl and mshtmext.pdl need to do, shouldn't special case.
  2854. BOOL fInternalPDL = (_stricmp(_pszPDLFileName, "internal.pdl") == 0) || (_stricmp(_pszPDLFileName, "mshtmext.pdl") == 0);
  2855. // Output COM+ code, only real classes are exposed.
  2856. if (pClass->IsSet(CLASS_GUID) && pClass->IsSet(CLASS_INTERFACE) && !fInternalPDL)
  2857. {
  2858. GenComPlusDeclarations(pClass, pPI + iVTbl);
  2859. }
  2860. #endif // COMPLUS_SHIM
  2861. }
  2862. }
  2863. return TRUE;
  2864. }
  2865. #ifdef COMPLUS_SHIM
  2866. void
  2867. CPDLParser::GenComPlusMethodsInInterfaces(Token *pInterfaceToken, Token *pClass /* =NULL */)
  2868. {
  2869. Token *pChildToken;
  2870. CString szMethodName;
  2871. CString szPropertyName;
  2872. CString argCStr;
  2873. CString resultCStr;
  2874. CTokenListWalker ChildWalker(pInterfaceToken);
  2875. while (pChildToken = ChildWalker.GetNext())
  2876. {
  2877. if (pChildToken->GetType() == TYPE_METHOD)
  2878. {
  2879. // ***TLL*** Need to handle vararg arguments. [METHOD_VARARG]
  2880. if (pChildToken->IsSet(METHOD_NOPROPDESC) &&
  2881. pChildToken->IsSet(METHOD_SZINTERFACEEXPOSE))
  2882. {
  2883. szMethodName = pChildToken->GetTagValue(METHOD_SZINTERFACEEXPOSE);
  2884. }
  2885. else
  2886. {
  2887. szMethodName = pChildToken->GetTagValue(METHOD_NAME);
  2888. }
  2889. if (GenComPlusArgumentSignature(pChildToken, resultCStr, argCStr))
  2890. {
  2891. fprintf(fpHComPlusFile, "\t%s %s %s;\n",
  2892. (LPCSTR)resultCStr,
  2893. (LPCSTR)szMethodName,
  2894. (LPCSTR)argCStr);
  2895. }
  2896. }
  2897. else // Property
  2898. {
  2899. if (pChildToken->IsSet(PROPERTY_NOPROPDESC) &&
  2900. pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE))
  2901. {
  2902. szPropertyName = pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE);
  2903. }
  2904. else
  2905. {
  2906. szPropertyName = pChildToken->GetTagValue(PROPERTY_NAME);
  2907. }
  2908. if (pChildToken->IsSet(PROPERTY_SET))
  2909. {
  2910. // ***TLL*** COM+: What happens to displaybind, bindable, hidden, restricted, nonbrowsable, source.
  2911. if (GenComPlusArgumentSignature(pChildToken, resultCStr, argCStr, SetProperty))
  2912. {
  2913. fprintf(fpHComPlusFile, "\t%s %s %s;\n",
  2914. (LPCSTR)resultCStr,
  2915. (LPCSTR)szPropertyName,
  2916. (LPCSTR)argCStr);
  2917. }
  2918. }
  2919. if (pChildToken->IsSet(PROPERTY_GET))
  2920. {
  2921. // ***TLL*** COM+: What happens to displaybind, bindable, hidden, restricted, nonbrowsable, source.
  2922. if (GenComPlusArgumentSignature(pChildToken, resultCStr, argCStr, GetProperty))
  2923. {
  2924. fprintf(fpHComPlusFile, "\t%s %s %s;\n",
  2925. (LPCSTR)resultCStr,
  2926. (LPCSTR)szPropertyName,
  2927. (LPCSTR)argCStr);
  2928. }
  2929. }
  2930. }
  2931. }
  2932. }
  2933. void
  2934. CPDLParser::GenComPlusInterfaces(Token *pInterfaceToken, char* pszSuper)
  2935. {
  2936. CString szInterf;
  2937. Token *pSuperInterf;
  2938. #if 0
  2939. if (_stricmp("IHTMLStyle", pInterfaceToken->GetTagValue(NAME_TAG)) == 0)
  2940. __asm { int 3 };
  2941. #endif
  2942. if (!PrimaryTearoff(pInterfaceToken) && (!pszSuper || !*pszSuper))
  2943. ReportError("COM+: Interfaces w/o tearoff need super:IDispatch\n");
  2944. // ***TLL*** COM+: For now don't expose any IUnknown derived classes.
  2945. if (_stricmp(pszSuper, "IUnknown") == 0)
  2946. return;
  2947. // Is the super derived from IUnknown?
  2948. szInterf = pszSuper;
  2949. pSuperInterf = FindInterface(szInterf);
  2950. if (pSuperInterf)
  2951. {
  2952. if (_stricmp(pSuperInterf->GetTagValue(INTERFACE_SUPER), "IUnknown") == 0)
  2953. return;
  2954. }
  2955. // ***TLL*** End of comment section
  2956. if (pInterfaceToken->IsSet(INTERFACE_CUSTOM) && pszSuper && *pszSuper)
  2957. {
  2958. fprintf(fpHComPlusFile, "[managed, com] interface %sCOMPLUS : public ICOMCookie, public %sCOMPLUS\n{\npublic:\n",
  2959. pInterfaceToken->GetTagValue(NAME_TAG),
  2960. pszSuper);
  2961. }
  2962. else
  2963. {
  2964. if (PrimaryTearoff(pInterfaceToken))
  2965. {
  2966. fprintf(fpHComPlusFile, "[managed, com] interface %sCOMPLUS : public ICOMCookie \n{\npublic:\n",
  2967. pInterfaceToken->GetTagValue(NAME_TAG));
  2968. }
  2969. else
  2970. {
  2971. if (strcmp("IDispatch", pszSuper) == 0)
  2972. {
  2973. fprintf(fpHComPlusFile, "[managed, com] interface %sCOMPLUS : public ICOMCookie \n{\npublic:\n",
  2974. pInterfaceToken->GetTagValue(NAME_TAG));
  2975. }
  2976. else
  2977. {
  2978. fprintf(fpHComPlusFile, "[managed, com] interface %sCOMPLUS : public ICOMCookie, public %sCOMPLUS \n{\npublic:\n",
  2979. pInterfaceToken->GetTagValue(NAME_TAG), pszSuper);
  2980. }
  2981. }
  2982. }
  2983. // Fill in methods of interface:
  2984. GenComPlusMethodsInInterfaces(pInterfaceToken);
  2985. fprintf(fpHComPlusFile, "};\n\n");
  2986. }
  2987. void
  2988. CPDLParser::GenComPlusESI()
  2989. {
  2990. CTokenListWalker ThisFileList(pRuntimeList, _pszPDLFileName);
  2991. Token * pInterfaceToken;
  2992. Token * pEnumToken;
  2993. Token * pStructToken;
  2994. //
  2995. // Generate all the event interfaces
  2996. //
  2997. ThisFileList.Reset();
  2998. while (pInterfaceToken = ThisFileList.GetNext(TYPE_EVENT))
  2999. {
  3000. if (!pInterfaceToken->IsSet(EVENT_ABSTRACT) &&
  3001. pInterfaceToken->IsSet(EVENT_GUID))
  3002. {
  3003. // TODO: ***TLL*** Need to spit out event interfaces.
  3004. }
  3005. }
  3006. //
  3007. // Generate all the enumerators.
  3008. //
  3009. ThisFileList.Reset();
  3010. while (pEnumToken = ThisFileList.GetNext(TYPE_ENUM))
  3011. {
  3012. // TODO: ***TLL*** Need to spit out enums.
  3013. }
  3014. //
  3015. // Generate all the structs
  3016. //
  3017. ThisFileList.Reset();
  3018. while (pStructToken = ThisFileList.GetNext(TYPE_STRUCT))
  3019. {
  3020. // TODO: ***TLL*** Need to spit out structs.
  3021. }
  3022. //
  3023. // Generate all the non-abstract interfaces.
  3024. //
  3025. ThisFileList.Reset();
  3026. while ( pInterfaceToken = ThisFileList.GetNext(TYPE_INTERFACE))
  3027. {
  3028. if (!pInterfaceToken->IsSet(INTERFACE_ABSTRACT) &&
  3029. pInterfaceToken->IsSet(INTERFACE_GUID))
  3030. {
  3031. GenComPlusInterfaces(pInterfaceToken, pInterfaceToken->GetTagValue(INTERFACE_SUPER));
  3032. }
  3033. else if (!pInterfaceToken->IsSet(INTERFACE_ABSTRACT) &&
  3034. !pInterfaceToken->IsSet(INTERFACE_GUID))
  3035. {
  3036. // Generate a forward declare
  3037. CString szInterfaceName;
  3038. szInterfaceName = pInterfaceToken->GetTagValue(INTERFACE_NAME);
  3039. if (szInterfaceName != "IDispatch" && szInterfaceName != "IUnknown")
  3040. {
  3041. fprintf(fpHComPlusFile, "interface %sCOMPLUS;\n", pInterfaceToken->GetTagValue(NAME_TAG));
  3042. }
  3043. }
  3044. }
  3045. }
  3046. BOOL
  3047. CPDLParser::GenComPlusArgumentSignature(Token *pMethod, CString & resultCStr, CString & argCStr, PropertyType propType /* = NotProperty */)
  3048. {
  3049. BOOL fNameOnly;
  3050. LPCSTR pSimpleType;
  3051. char pComPlusType[128];
  3052. BOOL fRet = FALSE; // Assume don't want to expose method/property
  3053. resultCStr = "";
  3054. argCStr = "";
  3055. fNameOnly = _stricmp(pMethod->GetTagValue(METHOD_NOPROPDESC), "nameonly") == 0;
  3056. if (pMethod->GetType() == TYPE_METHOD && !fNameOnly)
  3057. {
  3058. CTokenListWalker ArgListWalker(pMethod);
  3059. BOOL fResultFound = FALSE;
  3060. CString szAutomationType;
  3061. Token *pArgToken;
  3062. int cAType;
  3063. while (pArgToken = ArgListWalker.GetNext())
  3064. {
  3065. if (pArgToken->IsSet(METHODARG_RETURNVALUE))
  3066. {
  3067. szAutomationType = pArgToken->IsSet(METHODARG_ATYPE) ?
  3068. pArgToken->GetTagValue(METHODARG_ATYPE) :
  3069. pArgToken->GetTagValue(METHODARG_TYPE);
  3070. cAType = szAutomationType.Length();
  3071. if (cAType && szAutomationType[cAType - 2] == '*')
  3072. {
  3073. szAutomationType.PutChar(cAType - 2, '\0');
  3074. }
  3075. else if (cAType && szAutomationType[cAType - 1] == '*')
  3076. {
  3077. szAutomationType.PutChar(cAType - 1, '\0');
  3078. }
  3079. #if 0
  3080. if (szAutomationType == "IHTMLControlElement")
  3081. __asm {int 3};
  3082. #endif
  3083. pSimpleType = ConvertType(szAutomationType, TRUE, &pComPlusType[0]);
  3084. resultCStr = pSimpleType ? pSimpleType : pComPlusType;
  3085. fResultFound = TRUE;
  3086. }
  3087. }
  3088. if (!fResultFound)
  3089. {
  3090. resultCStr = "void";
  3091. }
  3092. BOOL fFirst = TRUE;
  3093. int idx = 1;
  3094. char buffer[40];
  3095. argCStr = "(";
  3096. ArgListWalker.Reset();
  3097. while (pArgToken = ArgListWalker.GetNext())
  3098. {
  3099. if (!pArgToken->IsSet(METHODARG_RETURNVALUE))
  3100. {
  3101. if (!fFirst)
  3102. {
  3103. argCStr += ", ";
  3104. }
  3105. szAutomationType = pArgToken->GetTagValue(METHODARG_TYPE);
  3106. cAType = szAutomationType.Length();
  3107. if (cAType && szAutomationType[cAType - 1] == '*')
  3108. {
  3109. szAutomationType.PutChar(cAType - 1, '\0');
  3110. }
  3111. pSimpleType = ConvertType(szAutomationType, TRUE, &pComPlusType[0]);
  3112. argCStr += pSimpleType ? pSimpleType : pComPlusType;
  3113. argCStr += " param";
  3114. _itoa(idx++, buffer, 10);
  3115. argCStr += buffer;
  3116. }
  3117. fFirst = FALSE;
  3118. }
  3119. argCStr += ")";
  3120. fRet = TRUE;
  3121. }
  3122. else
  3123. {
  3124. // Property
  3125. CString szAutomationType;
  3126. int cAType;
  3127. fNameOnly = _stricmp(pMethod->GetTagValue(PROPERTY_NOPROPDESC), "nameonly") == 0;
  3128. szAutomationType = pMethod->GetTagValue(PROPERTY_ATYPE);
  3129. cAType = szAutomationType.Length();
  3130. if (szAutomationType[cAType - 1] == '*')
  3131. {
  3132. szAutomationType.PutChar(cAType - 1, '\0');
  3133. }
  3134. pSimpleType = ConvertType(szAutomationType, TRUE, &pComPlusType[0]);
  3135. if (propType == SetProperty && !fNameOnly )
  3136. {
  3137. resultCStr = "void";
  3138. argCStr = "(";
  3139. argCStr += pSimpleType ? pSimpleType : pComPlusType;
  3140. argCStr += " param1)";
  3141. fRet = TRUE;
  3142. }
  3143. if (propType == GetProperty && !fNameOnly)
  3144. {
  3145. resultCStr = pSimpleType ? pSimpleType : pComPlusType;
  3146. argCStr = "()";
  3147. fRet = TRUE;
  3148. }
  3149. }
  3150. return fRet;
  3151. }
  3152. void
  3153. CPDLParser::GenComPlusDeclarations(Token *pClass, PropdescInfo *pPI)
  3154. {
  3155. BOOL fNameOnly;
  3156. LPCSTR pSimpleType;
  3157. char pComPlusType[128];
  3158. int uIIDIdx;
  3159. int uVTblIdx;
  3160. CString szClassName;
  3161. szClassName = pClass->IsSet(CLASS_COCLASSNAME) ? pClass->GetTagValue(CLASS_COCLASSNAME) : pClass->GetTagValue(CLASS_NAME);
  3162. #if 0
  3163. //if (pPI->_pToken->GetType() == TYPE_METHOD && _stricmp("fireEvent", (LPSTR)pPI->_pToken->GetTagValue(METHOD_NAME)) == 0)
  3164. if (pPI->_pToken->GetType() == TYPE_PROPERTY && _stricmp("bookmarks", (LPSTR)pPI->_pToken->GetTagValue(PROPERTY_NAME)) == 0)
  3165. __asm {int 3};
  3166. #endif
  3167. uIIDIdx = pPI->_uIIDIndex + 1; // zero is reserved for error.
  3168. uVTblIdx = (((pPI->_uVTblIndex & 0x00ff) + 7) * 4);
  3169. fNameOnly = _stricmp(pPI->_pToken->GetTagValue(METHOD_NOPROPDESC), "nameonly") == 0;
  3170. if (pPI->_pToken->GetType() == TYPE_METHOD && !fNameOnly)
  3171. {
  3172. CTokenListWalker ArgListWalker(pPI->_pToken);
  3173. BOOL fResultFound = FALSE;
  3174. CString szAutomationType;
  3175. Token *pArgToken;
  3176. int cAType;
  3177. CString szTypesSig;
  3178. CString szArgsType;
  3179. int cArgs = 0;
  3180. int cRequiredArgs = 0;
  3181. char *pDefaultParams[MAX_ARGS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
  3182. char *pDefaultStrParams[MAX_ARGS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
  3183. BOOL fBSTRArg;
  3184. BOOL fVARIANTArg;
  3185. BOOL fObjectReturn = FALSE;
  3186. ParamType objectParam[MAX_ARGS] = { CPDLParser::None, CPDLParser::None, CPDLParser::None, CPDLParser::None, CPDLParser::None, CPDLParser::None, CPDLParser::None, CPDLParser::None };
  3187. while (pArgToken = ArgListWalker.GetNext())
  3188. {
  3189. if (pArgToken->IsSet(METHODARG_RETURNVALUE))
  3190. {
  3191. szAutomationType = pArgToken->IsSet(METHODARG_ATYPE) ?
  3192. pArgToken->GetTagValue(METHODARG_ATYPE) :
  3193. pArgToken->GetTagValue(METHODARG_TYPE);
  3194. cAType = szAutomationType.Length();
  3195. if (cAType && szAutomationType[cAType - 2] == '*')
  3196. {
  3197. szAutomationType.PutChar(cAType - 2, '\0');
  3198. fObjectReturn = szAutomationType != "Variant";
  3199. }
  3200. else if (cAType && szAutomationType[cAType - 1] == '*')
  3201. {
  3202. szAutomationType.PutChar(cAType - 1, '\0');
  3203. fObjectReturn = szAutomationType != "Variant";
  3204. }
  3205. pSimpleType = ConvertType(szAutomationType, TRUE, &pComPlusType[0]);
  3206. if (pSimpleType)
  3207. {
  3208. // IUknown or IDispatch return value is an unsigned int from CPThunks
  3209. if (_stricmp(pSimpleType, "Object") != 0)
  3210. {
  3211. // VARIANT_BOOL, int's, etc. returned are not objects.
  3212. fObjectReturn = FALSE;
  3213. }
  3214. }
  3215. fprintf(fpCComPlusFile, "%s\n", pSimpleType ? pSimpleType : pComPlusType);
  3216. if (!pSimpleType)
  3217. {
  3218. if (_stricmp(pComPlusType, "Object") == 0)
  3219. {
  3220. strcpy(pComPlusType, "unsigned int");
  3221. }
  3222. }
  3223. fprintf(fpHComPlusFile, "\t%s ", pSimpleType ? pSimpleType : pComPlusType);
  3224. fResultFound = TRUE;
  3225. }
  3226. }
  3227. if (!fResultFound)
  3228. {
  3229. fprintf(fpHComPlusFile, "\tvoid ");
  3230. fprintf(fpCComPlusFile, "void\n");
  3231. }
  3232. fprintf(fpCComPlusFile, "%sCOMPLUS::", (LPCSTR)szClassName);
  3233. // Method
  3234. fprintf(fpHComPlusFile, "\t%s (", pPI->_pToken->IsSet(METHOD_SZINTERFACEEXPOSE) ?
  3235. (LPSTR)pPI->_pToken->GetTagValue(METHOD_SZINTERFACEEXPOSE) :
  3236. (LPSTR)pPI->_pToken->GetTagValue(METHOD_NAME));
  3237. fprintf(fpCComPlusFile, "%s (", pPI->_pToken->IsSet(METHOD_SZINTERFACEEXPOSE) ?
  3238. (LPSTR)pPI->_pToken->GetTagValue(METHOD_SZINTERFACEEXPOSE) :
  3239. (LPSTR)pPI->_pToken->GetTagValue(METHOD_NAME));
  3240. BOOL fFirst = TRUE;
  3241. int idx = 1;
  3242. BOOL fAnyDynamicCasts = FALSE;
  3243. ArgListWalker.Reset();
  3244. while (pArgToken = ArgListWalker.GetNext())
  3245. {
  3246. if (!pArgToken->IsSet(METHODARG_RETURNVALUE))
  3247. {
  3248. if (!fFirst)
  3249. {
  3250. fprintf(fpHComPlusFile, ", ");
  3251. fprintf(fpCComPlusFile, ", ");
  3252. }
  3253. szAutomationType = pArgToken->GetTagValue(METHODARG_TYPE);
  3254. cAType = szAutomationType.Length();
  3255. if (cAType && szAutomationType[cAType - 1] == '*')
  3256. {
  3257. szAutomationType.PutChar(cAType - 1, '\0');
  3258. if (szAutomationType == "IUnknown" || szAutomationType == "IDispatch")
  3259. {
  3260. objectParam[idx - 1] = CPDLParser::AnyObject;
  3261. }
  3262. else if (szAutomationType != "Variant")
  3263. {
  3264. objectParam[idx - 1] = CPDLParser::Object;
  3265. }
  3266. }
  3267. pSimpleType = ConvertType(szAutomationType, TRUE, &pComPlusType[0]);
  3268. if (pSimpleType)
  3269. {
  3270. // IUknown or IDispatch return value is an unsigned int from CPThunks
  3271. if (_stricmp(pSimpleType, "Object") != 0)
  3272. {
  3273. // VARIANT_BOOL, int's, etc. returned are not objects.
  3274. objectParam[idx - 1] = CPDLParser::None;
  3275. }
  3276. }
  3277. fprintf(fpHComPlusFile, "%s param%i", pSimpleType ? pSimpleType : pComPlusType, idx);
  3278. fprintf(fpCComPlusFile, "%s param%i", pSimpleType ? pSimpleType : pComPlusType, idx++);
  3279. }
  3280. fFirst = FALSE;
  3281. }
  3282. fprintf(fpHComPlusFile, ");\n");
  3283. fprintf(fpCComPlusFile, ")\n");
  3284. fprintf(fpCComPlusFile, "{\n");
  3285. if (BuildMethodSignature(pPI->_pToken,
  3286. szTypesSig,
  3287. szArgsType,
  3288. fBSTRArg,
  3289. fVARIANTArg,
  3290. cArgs,
  3291. cRequiredArgs,
  3292. pDefaultParams,
  3293. pDefaultStrParams))
  3294. {
  3295. CString szFullSignature;
  3296. BOOL fAtLeastOne = FALSE;
  3297. int i;
  3298. if (fObjectReturn)
  3299. {
  3300. fprintf(fpCComPlusFile, "\tunsigned int myPDispatch;\n\n");
  3301. }
  3302. for (i = 0; i < cArgs; i++)
  3303. {
  3304. if (objectParam[i] & CPDLParser::GenericObject)
  3305. {
  3306. fprintf(fpCComPlusFile, "\tICOMCookie tempParam%i = dynamic_cast<ICOMCookie>(param%i);\n", i + 1, i + 1);
  3307. fAtLeastOne = TRUE;
  3308. }
  3309. }
  3310. if (fAtLeastOne)
  3311. {
  3312. fprintf(fpCComPlusFile, "\n");
  3313. }
  3314. // If no return value then set the retVal to void.
  3315. if (!szTypesSig[0])
  3316. {
  3317. szTypesSig = "void";
  3318. }
  3319. // If no arguments then set the argList to void.
  3320. if (!szArgsType[0])
  3321. {
  3322. szArgsType = "_void";
  3323. }
  3324. szTypesSig += szArgsType;
  3325. MakeSignature("Method", szTypesSig, szFullSignature);
  3326. if (fResultFound)
  3327. {
  3328. fprintf(fpCComPlusFile, "\t%s", fObjectReturn ? "myPDispatch = " : "return ");
  3329. }
  3330. else
  3331. {
  3332. fprintf(fpCComPlusFile, "\t");
  3333. }
  3334. fprintf(fpCComPlusFile, "CPThunks::COMPLUS_%s(_myThis, %i, %i", (LPCSTR)szFullSignature, uIIDIdx, uVTblIdx);
  3335. for (i = 0; i < cArgs; i++)
  3336. {
  3337. if (objectParam[i] & CPDLParser::GenericObject)
  3338. {
  3339. fprintf(fpCComPlusFile, ", tempParam%i.getCOMCookie()", i + 1);
  3340. }
  3341. else if (objectParam[i] & CPDLParser::Object)
  3342. {
  3343. fprintf(fpCComPlusFile, ", param%i.getCOMCookie()", i + 1);
  3344. }
  3345. else
  3346. {
  3347. fprintf(fpCComPlusFile, ", param%i", i + 1);
  3348. }
  3349. }
  3350. fprintf(fpCComPlusFile, ");\n");
  3351. }
  3352. if (fObjectReturn)
  3353. {
  3354. // ***TLL*** COM+: Need to create class for return value. For now just return 0.
  3355. // Should be something like "return new HTMLDOMNodeCOMPLUS(myPDispatch)" where HTMLDOMNodeCOMPLUS
  3356. // is a COM+ class.
  3357. if (fObjectReturn)
  3358. {
  3359. fprintf(fpCComPlusFile, "\n");
  3360. }
  3361. fprintf(fpCComPlusFile, "\treturn 0;\n");
  3362. }
  3363. fprintf(fpCComPlusFile, "}\n\n");
  3364. }
  3365. else
  3366. {
  3367. // Property
  3368. CString szAutomationType;
  3369. int cAType;
  3370. ParamType propertyParam = CPDLParser::None;
  3371. BOOL fInterfaceFound;
  3372. fNameOnly = _stricmp(pPI->_pToken->GetTagValue(PROPERTY_NOPROPDESC), "nameonly") == 0;
  3373. szAutomationType = pPI->_pToken->GetTagValue(PROPERTY_ATYPE);
  3374. cAType = szAutomationType.Length();
  3375. if (szAutomationType[cAType - 1] == '*')
  3376. {
  3377. szAutomationType.PutChar(cAType - 1, '\0');
  3378. }
  3379. if (cAType && szAutomationType[cAType - 1] == '*')
  3380. {
  3381. szAutomationType.PutChar(cAType - 1, '\0');
  3382. if (szAutomationType == "IUnknown" || szAutomationType == "IDispatch")
  3383. {
  3384. propertyParam = CPDLParser::AnyObject;
  3385. }
  3386. else if (szAutomationType != "Variant")
  3387. {
  3388. propertyParam = CPDLParser::Object;
  3389. }
  3390. }
  3391. pSimpleType = ConvertType(szAutomationType, TRUE, &pComPlusType[0], &fInterfaceFound);
  3392. if (pSimpleType)
  3393. {
  3394. // IUknown or IDispatch return value is an unsigned int from CPThunks
  3395. if (_stricmp(pSimpleType, "Object") != 0)
  3396. {
  3397. // VARIANT_BOOL, int's, etc. returned are not objects.
  3398. propertyParam = CPDLParser::None;
  3399. }
  3400. }
  3401. if (pPI->_pToken->IsSet(PROPERTY_SET) && !fNameOnly )
  3402. {
  3403. fprintf(fpHComPlusFile, "\tvoid\t%s (%s param1);\n",
  3404. pPI->_pToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
  3405. (LPSTR)pPI->_pToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
  3406. (LPSTR)pPI->_pToken->GetTagValue(PROPERTY_NAME),
  3407. pSimpleType ? pSimpleType : pComPlusType);
  3408. fprintf(fpCComPlusFile, "void\n%sCOMPLUS::%s (%s param1)\n",
  3409. (LPCSTR)szClassName,
  3410. pPI->_pToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
  3411. (LPSTR)pPI->_pToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
  3412. (LPSTR)pPI->_pToken->GetTagValue(PROPERTY_NAME),
  3413. pSimpleType ? pSimpleType : pComPlusType);
  3414. fprintf(fpCComPlusFile, "{\n");
  3415. if (pSimpleType)
  3416. {
  3417. if (_stricmp(pSimpleType, "String") == 0)
  3418. {
  3419. fprintf(fpCComPlusFile, "\tCPThunks::COMPLUS_S_String(_myThis, %i, %i, param1);\n", uIIDIdx, uVTblIdx);
  3420. }
  3421. else if (_stricmp(pSimpleType, "Object") == 0 )
  3422. {
  3423. fprintf(fpCComPlusFile, "\tunsigned int tempParam1 = dynamic_cast<ICOMCookie>(param1).getCOMCookie();\n");
  3424. fprintf(fpCComPlusFile, "\tCPThunks::COMPLUS_S_IDispatchp(_myThis, %i, %i, tempParam1);\n", pSimpleType, uIIDIdx, uVTblIdx);
  3425. }
  3426. else
  3427. {
  3428. fprintf(fpCComPlusFile, "\tCPThunks::COMPLUS_S_%s(_myThis, %i, %i, param1);\n", pSimpleType, uIIDIdx, uVTblIdx);
  3429. }
  3430. }
  3431. else if (fInterfaceFound)
  3432. {
  3433. fprintf(fpCComPlusFile, "\tCPThunks::COMPLUS_S_IDispatchp(_myThis, %i, %i, param1.getCOMCookie());\n", uIIDIdx, uVTblIdx);
  3434. }
  3435. else
  3436. {
  3437. fprintf(fpCComPlusFile, "\tCPThunks::COMPLUS_S_%s(_myThis, %i, %i, param1);\n", pComPlusType, uIIDIdx, uVTblIdx);
  3438. }
  3439. fprintf(fpCComPlusFile, "}\n\n");
  3440. }
  3441. if (pPI->_pToken->IsSet(PROPERTY_GET) && !fNameOnly)
  3442. {
  3443. fprintf(fpHComPlusFile, "\t%s\t%s ();\n",
  3444. pSimpleType ? pSimpleType : pComPlusType,
  3445. pPI->_pToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
  3446. (LPSTR)pPI->_pToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
  3447. (LPSTR)pPI->_pToken->GetTagValue(PROPERTY_NAME));
  3448. fprintf(fpCComPlusFile, "%s\n%sCOMPLUS::%s ()\n",
  3449. pSimpleType ? pSimpleType : pComPlusType,
  3450. (LPCSTR)szClassName,
  3451. pPI->_pToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
  3452. (LPSTR)pPI->_pToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
  3453. (LPSTR)pPI->_pToken->GetTagValue(PROPERTY_NAME));
  3454. fprintf(fpCComPlusFile, "{\n");
  3455. if (pSimpleType)
  3456. {
  3457. if (_stricmp(pSimpleType, "String") == 0)
  3458. {
  3459. fprintf(fpCComPlusFile, "\treturn CPThunks::COMPLUS_G_String(_myThis, %i, %i);\n", uIIDIdx, uVTblIdx + 1);
  3460. }
  3461. else if (_stricmp(pSimpleType, "Object") == 0)
  3462. {
  3463. // return IUnknown or IDispatch (not a qualified interface like IHTMLnnnnn).
  3464. fprintf(fpCComPlusFile, "\tunsigned int\tmyPDispatch;\n\n");
  3465. fprintf(fpCComPlusFile, "\tmyPDispatch = CPThunks::COMPLUS_G_%s(_myThis, %i, %i);\n", pSimpleType, uIIDIdx, uVTblIdx + 1);
  3466. //TODO: ***TLL*** COM+: Hook up document property of Window. Need generic mechanism here.
  3467. if (_stricmp((LPCSTR)szClassName, "HTMLWindow2") == 0)
  3468. {
  3469. if (_stricmp(pPI->_pToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
  3470. (LPSTR)pPI->_pToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
  3471. (LPSTR)pPI->_pToken->GetTagValue(PROPERTY_NAME),
  3472. "document") == 0)
  3473. {
  3474. fprintf(fpCComPlusFile, "return new HTMLDocumentCOMPLUS(myPDispatch);\n");
  3475. fprintf(fpCComPlusFile, "//"); // comment the next return spit out
  3476. }
  3477. }
  3478. // TODO: ***TLL*** COM+: Need to return (coclass) object stuffed myPDispatch. Remove return 0; and used below commented out line.
  3479. fprintf(fpCComPlusFile, "\treturn 0;\n");
  3480. // fprintf(fpCComPlusFile, "\treturn new %s(myPDispatch);\n", pComPlusType);
  3481. }
  3482. else
  3483. {
  3484. fprintf(fpCComPlusFile, "\treturn CPThunks::COMPLUS_G_%s(_myThis, %i, %i);\n", pSimpleType, uIIDIdx, uVTblIdx + 1);
  3485. }
  3486. }
  3487. else if (_stricmp(pComPlusType, "Variant") == 0)
  3488. {
  3489. fprintf(fpCComPlusFile, "\tunsigned int\tmyPVariant;\n\n");
  3490. fprintf(fpCComPlusFile, "\tmyPVariant = CPThunks::COMPLUS_G_%s(_myThis, %i, %i);\n\n", "VARIANT", uIIDIdx, uVTblIdx + 1);
  3491. fprintf(fpCComPlusFile, "\treturn new Variant(myPVariant);\n");
  3492. }
  3493. else
  3494. {
  3495. fprintf(fpCComPlusFile, "\tunsigned int\tmyPDispatch;\n\n");
  3496. fprintf(fpCComPlusFile, "\tmyPDispatch = CPThunks::COMPLUS_G_%s(_myThis, %i, %i);\n\n", "Object", uIIDIdx, uVTblIdx + 1);
  3497. //TODO: ***TLL*** COM+: Hook up document property of Window. Need generic mechanism here.
  3498. if (_stricmp((LPCSTR)szClassName, "HTMLWindow2") == 0)
  3499. {
  3500. if (_stricmp(pPI->_pToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
  3501. (LPSTR)pPI->_pToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
  3502. (LPSTR)pPI->_pToken->GetTagValue(PROPERTY_NAME),
  3503. "document") == 0)
  3504. {
  3505. fprintf(fpCComPlusFile, "return new HTMLDocumentCOMPLUS(myPDispatch);\n");
  3506. fprintf(fpCComPlusFile, "//"); // comment the next return spit out
  3507. }
  3508. }
  3509. // ***TLL*** COM+: Need to return (coclass) object stuffed myPDispatch. Remove return 0; and used below commented out line.
  3510. fprintf(fpCComPlusFile, "\treturn 0;\n");
  3511. // fprintf(fpCComPlusFile, "\treturn new %s(myPDispatch);\n", pComPlusType);
  3512. }
  3513. fprintf(fpCComPlusFile, "}\n\n");
  3514. }
  3515. }
  3516. }
  3517. #endif // COMPLUS_SHIM
  3518. BOOL
  3519. CPDLParser::ComputePROPDESC_STRUCT ( FILE *fp, Token *pClassToken, Token *pChild, CString & szHandler, CString & szFnPrefix )
  3520. {
  3521. char szErrorText [ MAX_LINE_LEN+1 ];
  3522. fprintf ( fp, "EXTERN_C const " );
  3523. if ( !pChild->IsSet ( PROPERTY_ABSTRACT ) && szHandler == "Num" || szHandler == "Enum" || szHandler == "UnitValue" )
  3524. {
  3525. // Numeric Handlers
  3526. if ( pChild->IsSet ( PROPERTY_GETSETMETHODS ) )
  3527. {
  3528. fprintf ( fp, "PROPERTYDESC_NUMPROP_GETSET" );
  3529. }
  3530. else if ( pChild->IsSet ( PROPERTY_ABSTRACT ) )
  3531. {
  3532. fprintf ( fp, "PROPERTYDESC_NUMPROP_ABSTRACT" );
  3533. }
  3534. else if ( pChild->IsSet ( PROPERTY_ENUMREF ) )
  3535. {
  3536. fprintf ( fp, "PROPERTYDESC_NUMPROP_ENUMREF" );
  3537. }
  3538. else
  3539. {
  3540. fprintf ( fp, "PROPERTYDESC_NUMPROP" );
  3541. }
  3542. }
  3543. else
  3544. {
  3545. // BASIC PROP PARAM Structure
  3546. if ( pChild->IsSet ( PROPERTY_GETSETMETHODS ) )
  3547. {
  3548. if ( szFnPrefix == "" )
  3549. {
  3550. sprintf ( szErrorText, "Invalid Type:%s in Class:%s Property:%s\n",
  3551. (LPCSTR)pChild->GetTagValue ( PROPERTY_TYPE ),
  3552. (LPCSTR)pClassToken->GetTagValue(CLASS_NAME),
  3553. (LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ) );
  3554. ReportError ( szErrorText );
  3555. return FALSE;
  3556. }
  3557. fprintf ( fp, "PROPERTYDESC_%s_GETSET", (LPCSTR)szFnPrefix );
  3558. }
  3559. else if ( pChild->IsSet ( PROPERTY_ABSTRACT ) )
  3560. {
  3561. fprintf ( fp, "PROPERTYDESC_BASIC_ABSTRACT" );
  3562. }
  3563. else
  3564. {
  3565. fprintf ( fp, "PROPERTYDESC_BASIC" );
  3566. }
  3567. }
  3568. return TRUE;
  3569. }
  3570. Token * CPDLParser::FindEnum ( Token *pChild )
  3571. {
  3572. // Get the enum mask from the enum named by PROPERTY_TYPE
  3573. CTokenListWalker WholeList ( pRuntimeList );
  3574. return WholeList.GetNext ( TYPE_ENUM, pChild->GetTagValue ( PROPERTY_TYPE ) );
  3575. }
  3576. char * CPDLParser::MapTypeToIDispatch ( CString & szType )
  3577. {
  3578. CString szHandler;
  3579. CString szFnPrefix;
  3580. char szStrType[255];
  3581. strcpy(szStrType, (LPCSTR)szType);
  3582. if (GetTypeDetails (szStrType, szHandler, szFnPrefix, NULL) && (szHandler == "object"))
  3583. {
  3584. int cSz = szType.Length();
  3585. if (szType[cSz - 1] == '*' && szType[cSz - 2] == '*')
  3586. {
  3587. // is it an IUnknown or an IDispatch?
  3588. if (_strnicmp(szType, "IUnknown", cSz-2)==0)
  3589. return "IUnknownpp";
  3590. else
  3591. return "IDispatchpp";
  3592. }
  3593. else if (szType[cSz - 1] == '*')
  3594. {
  3595. // is it an IUnknown or an IDispatch?
  3596. if (_strnicmp(szType, "IUnknown",cSz-1)==0)
  3597. return "IUnknownp";
  3598. else
  3599. return "IDispatchp";
  3600. }
  3601. }
  3602. return NULL;
  3603. }
  3604. Token * CPDLParser::FindEventMethod(Token *pClassToken, LPCSTR szEvent)
  3605. {
  3606. Token *pChildToken;
  3607. CTokenListWalker WholeList(pRuntimeList);
  3608. WholeList.Reset();
  3609. Token *pEventToken = WholeList.GetNext(TYPE_EVENT, pClassToken->GetTagValue(CLASS_EVENTS));
  3610. if (pEventToken)
  3611. {
  3612. CTokenListWalker ChildList(pEventToken);
  3613. while (pChildToken = ChildList.GetNext())
  3614. {
  3615. if (_stricmp(pChildToken->GetTagValue(METHOD_NAME), szEvent) == 0)
  3616. return pChildToken;
  3617. }
  3618. }
  3619. WholeList.Reset();
  3620. pEventToken = WholeList.GetNext(TYPE_EVENT, pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS1));
  3621. if (!pEventToken)
  3622. return NULL;
  3623. {
  3624. CTokenListWalker ChildList(pEventToken);
  3625. while (pChildToken = ChildList.GetNext())
  3626. {
  3627. if (_stricmp(pChildToken->GetTagValue(METHOD_NAME), szEvent) == 0)
  3628. return pChildToken;
  3629. }
  3630. }
  3631. WholeList.Reset();
  3632. pEventToken = WholeList.GetNext(TYPE_EVENT, pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS2));
  3633. if (!pEventToken)
  3634. return NULL;
  3635. {
  3636. CTokenListWalker ChildList(pEventToken);
  3637. while (pChildToken = ChildList.GetNext())
  3638. {
  3639. if (_stricmp(pChildToken->GetTagValue(METHOD_NAME), szEvent) == 0)
  3640. return pChildToken;
  3641. }
  3642. }
  3643. WholeList.Reset();
  3644. pEventToken = WholeList.GetNext(TYPE_EVENT, pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS3));
  3645. if (!pEventToken)
  3646. return NULL;
  3647. {
  3648. CTokenListWalker ChildList(pEventToken);
  3649. while (pChildToken = ChildList.GetNext())
  3650. {
  3651. if (_stricmp(pChildToken->GetTagValue(METHOD_NAME), szEvent) == 0)
  3652. return pChildToken;
  3653. }
  3654. }
  3655. WholeList.Reset();
  3656. pEventToken = WholeList.GetNext(TYPE_EVENT, pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS4));
  3657. if (!pEventToken)
  3658. return NULL;
  3659. {
  3660. CTokenListWalker ChildList(pEventToken);
  3661. while (pChildToken = ChildList.GetNext())
  3662. {
  3663. if (_stricmp(pChildToken->GetTagValue(METHOD_NAME), szEvent) == 0)
  3664. return pChildToken;
  3665. }
  3666. }
  3667. return NULL;
  3668. }
  3669. Token * CPDLParser::FindEventProp(Token *pClassToken, LPCSTR szEvent)
  3670. {
  3671. Token *pChild;
  3672. CTokenListWalker ChildList ( pClassToken );
  3673. while ( pChild = ChildList.GetNext() )
  3674. {
  3675. if ( pChild->nType == TYPE_PROPERTY &&
  3676. pChild->IsSet(PROPERTY_SCRIPTLET) &&
  3677. _stricmp(pChild->GetTagValue(PROPERTY_NAME), szEvent) == 0 )
  3678. return pChild;
  3679. }
  3680. return NULL;
  3681. }
  3682. BOOL CPDLParser::ComputeProperty ( Token *pClassToken, Token *pChild )
  3683. {
  3684. CString szClass;
  3685. CString szHandler;
  3686. CString szFnPrefix;
  3687. CString szHTMLName;
  3688. char szExposedName [ MAX_LINE_LEN+1 ];
  3689. CString szdwFlags;
  3690. CString szNotPresentDefault;
  3691. CString szNotAssignedDefault;
  3692. CString szUpperName;
  3693. CString szDispid;
  3694. char szErrorText [ MAX_LINE_LEN+1 ];
  3695. StorageType stHowStored;
  3696. const CCachedAttrArrayInfo *pCAAI = NULL;
  3697. BOOL fNumericHandler;
  3698. CString szVTDef;
  3699. CString szPropSignature;
  3700. CString szPropVT;
  3701. Token *pEnumType;
  3702. Token *pEventChild = NULL;
  3703. char chCustomInvokeIdx[128];
  3704. char *pDispatchType;
  3705. CString szPreText,szPostText;
  3706. CString szMemberDesc;
  3707. szPreText = "_T(";
  3708. szPostText = ")";
  3709. pEnumType = FindEnum ( pChild );
  3710. if ( pEnumType )
  3711. {
  3712. // Generic enumerator property handler, the propDesc has the enumerator
  3713. // type.
  3714. szPropVT = "PropEnum";
  3715. }
  3716. else
  3717. {
  3718. char *pWS;
  3719. szPropVT = pChild->GetTagValue ( PROPERTY_ATYPE );
  3720. // Remove any underscores in the type name.
  3721. while ((pWS = szPropVT.FindChar('_')))
  3722. {
  3723. while (*pWS = *(pWS + 1))
  3724. pWS++;
  3725. *pWS = '\0';
  3726. }
  3727. }
  3728. // Should this type be mapped to IDispatch?
  3729. pDispatchType = MapTypeToIDispatch ( szPropVT );
  3730. if (pDispatchType)
  3731. {
  3732. szPropVT = pDispatchType;
  3733. }
  3734. szClass = pClassToken->GetTagValue ( CLASS_NAME );
  3735. szUpperName = pChild->GetTagValue ( PROPERTY_NAME );
  3736. szUpperName.ToUpper();
  3737. szHandler = "";
  3738. szFnPrefix = "";
  3739. // Check for missing handler later
  3740. GetTypeDetails ( pChild->GetTagValue ( PROPERTY_TYPE ),
  3741. szHandler, szFnPrefix, &stHowStored );
  3742. CString szPropParamDesc;
  3743. szdwFlags = pChild->GetTagValue ( PROPERTY_DWFLAGS );
  3744. if ( pChild->IsSet ( PROPERTY_GETSETMETHODS ) )
  3745. {
  3746. szPropParamDesc = "PROPPARAM_GETMFHandler | PROPPARAM_SETMFHandler";
  3747. szPropSignature = "GS";
  3748. }
  3749. else if ( pChild->IsSet ( PROPERTY_MEMBER ) )
  3750. {
  3751. szPropParamDesc = "PROPPARAM_MEMBER";
  3752. }
  3753. else
  3754. {
  3755. szPropParamDesc = "";
  3756. }
  3757. if ( pChild->IsSet ( PROPERTY_GET ) )
  3758. {
  3759. szPropSignature = "G";
  3760. if ( szPropParamDesc [ 0 ] )
  3761. szPropParamDesc += " | ";
  3762. szPropParamDesc += "PROPPARAM_INVOKEGet";
  3763. }
  3764. if ( pChild->IsSet ( PROPERTY_SET ) )
  3765. {
  3766. szPropSignature += "S";
  3767. if ( szPropParamDesc [ 0 ] )
  3768. szPropParamDesc += " | ";
  3769. szPropParamDesc += "PROPPARAM_INVOKESet";
  3770. }
  3771. if (!szPropSignature[0])
  3772. {
  3773. szPropSignature = "GS";
  3774. if ( szPropParamDesc [ 0 ] )
  3775. szPropParamDesc += " | ";
  3776. szPropParamDesc += "PROPPARAM_INVOKEGet | PROPPARAM_INVOKESet";
  3777. }
  3778. // Write out the function signature for this property.
  3779. if ( !FindAndAddSignature ( szPropSignature, szPropVT, &chCustomInvokeIdx[0] ) )
  3780. return FALSE;
  3781. if ( pChild->IsSet ( PROPERTY_PPFLAGS ))
  3782. {
  3783. szPropParamDesc += " | ";
  3784. szPropParamDesc += pChild->GetTagValue ( PROPERTY_PPFLAGS );
  3785. }
  3786. if ( pChild->IsSet ( PROPERTY_NOPERSIST ) )
  3787. {
  3788. szPropParamDesc += " | PROPPARAM_NOPERSIST";
  3789. }
  3790. if ( pChild->IsSet ( PROPERTY_INVALIDASNOASSIGN ) )
  3791. {
  3792. szPropParamDesc += " | PROPPARAM_INVALIDASNOASSIGN";
  3793. }
  3794. if ( pChild->IsSet ( PROPERTY_CUSTOMENUM ) )
  3795. {
  3796. szPropParamDesc += " | PROPPARAM_CUSTOMENUM ";
  3797. }
  3798. if ( pChild->IsSet ( PROPERTY_NOTPRESENTASDEFAULT ) )
  3799. {
  3800. szPropParamDesc += " | PROPPARAM_NOTPRESENTASDEFAULT";
  3801. }
  3802. if ( pChild->IsSet ( PROPERTY_HIDDEN ) )
  3803. {
  3804. szPropParamDesc += " | PROPPARAM_HIDDEN";
  3805. }
  3806. if ( pChild->IsSet ( PROPERTY_RESTRICTED ) )
  3807. {
  3808. szPropParamDesc += " | PROPPARAM_RESTRICTED";
  3809. }
  3810. if ( pChild->IsSet ( PROPERTY_CAA ) )
  3811. {
  3812. szDispid = pChild->GetTagValue( PROPERTY_DISPID );
  3813. pCAAI = GetCachedAttrArrayInfo(szDispid);
  3814. szPropParamDesc += " | PROPPARAM_ATTRARRAY ";
  3815. #if 0
  3816. if (pCAAI->szPPFlags)
  3817. {
  3818. szPropParamDesc += " | ";
  3819. szPropParamDesc += pCAAI->szPPFlags;
  3820. }
  3821. if (pCAAI->szLMinBitMask)
  3822. {
  3823. pChild->AddTag( PROPERTY_MIN , pCAAI->szLMinBitMask );
  3824. }
  3825. #endif
  3826. }
  3827. if ( pChild->IsSet ( PROPERTY_MINOUT ) )
  3828. {
  3829. szPropParamDesc += " | PROPPARAM_MINOUT";
  3830. }
  3831. if ( pChild->IsSet ( PROPERTY_SETDESIGNMODE ) )
  3832. {
  3833. szPropParamDesc += " | PROPPARAM_READONLYATRUNTIME";
  3834. }
  3835. // If we're processing a property that applies to a CF/PF/SF/FF, mark it here
  3836. // this helps us optimize the apply process. Only properties with a DISPID that
  3837. // matches our apply table, can be applied
  3838. if ( pCAAI && pCAAI->szDispId != NULL )
  3839. {
  3840. szPropParamDesc += " | PROPPARAM_STYLISTIC_PROPERTY";
  3841. }
  3842. if ( pChild -> IsSet ( PROPERTY_SCRIPTLET ) )
  3843. {
  3844. szPropParamDesc += " | PROPPARAM_SCRIPTLET";
  3845. pEventChild = FindEventMethod(pClassToken, pChild->GetTagValue(PROPERTY_NAME));
  3846. if (pEventChild)
  3847. {
  3848. if (pEventChild->IsSet(METHOD_CANCELABLE))
  3849. {
  3850. szPropParamDesc += " | PROPPARAM_CANCELABLE";
  3851. }
  3852. if (pEventChild->IsSet(METHOD_BUBBLING))
  3853. {
  3854. szPropParamDesc += " | PROPPARAM_BUBBLING";
  3855. }
  3856. }
  3857. else if (!pChild->IsSet(PROPERTY_NOPROPDESC) && !pChild->IsSet(PROPERTY_BASEIMPLEMENTATION))
  3858. {
  3859. sprintf ( szErrorText, "Unexpected Error:Event prop:%s in Class:%s not found in any Events interface defn.\n",
  3860. (LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ),
  3861. (LPCSTR)pClassToken->GetTagValue(CLASS_NAME) );
  3862. ReportError ( szErrorText );
  3863. return FALSE;
  3864. }
  3865. }
  3866. szMemberDesc = "";
  3867. if ( pChild->IsSet ( PROPERTY_CAA ) )
  3868. {
  3869. if ( pCAAI->dwFlags & CCSSF_CLEARCACHES )
  3870. {
  3871. // Always add dwFlags:ELEMCHNG_CLEARCACHES for these properties
  3872. if ( szdwFlags [0] )
  3873. {
  3874. szdwFlags += "|";
  3875. }
  3876. else
  3877. {
  3878. szdwFlags = "";
  3879. }
  3880. szdwFlags+="ELEMCHNG_CLEARCACHES";
  3881. }
  3882. if ( pCAAI->dwFlags & CCSSF_CLEARFF )
  3883. {
  3884. // Always add dwFlags:ELEMCHNG_CLEARFF for these properties
  3885. if ( szdwFlags [0] )
  3886. {
  3887. szdwFlags += "|";
  3888. }
  3889. else
  3890. {
  3891. szdwFlags = "";
  3892. }
  3893. szdwFlags+="ELEMCHNG_CLEARFF";
  3894. }
  3895. if ( pCAAI->dwFlags & CCSSF_REMEASURECONTENTS )
  3896. {
  3897. // Always add dwFlags:ELEMCHNG_REMEASURECONTENTS for these properties
  3898. if ( szdwFlags [0] )
  3899. {
  3900. szdwFlags += "|";
  3901. }
  3902. else
  3903. {
  3904. szdwFlags = "";
  3905. }
  3906. szdwFlags+="ELEMCHNG_REMEASURECONTENTS";
  3907. }
  3908. if ( pCAAI->dwFlags & CCSSF_REMEASUREALLCONTENTS )
  3909. {
  3910. // Always add dwFlags:ELEMCHNG_REMEASURECONTENTS for these properties
  3911. if ( szdwFlags [0] )
  3912. {
  3913. szdwFlags += "|";
  3914. }
  3915. else
  3916. {
  3917. szdwFlags = "";
  3918. }
  3919. szdwFlags+="ELEMCHNG_REMEASUREALLCONTENTS";
  3920. }
  3921. if ( pCAAI->dwFlags & CCSSF_REMEASUREINPARENT )
  3922. {
  3923. // Always add dwFlags:ELEMCHNG_REMEASUREINPARENT for these properties
  3924. if ( szdwFlags [0] )
  3925. {
  3926. szdwFlags += "|";
  3927. }
  3928. else
  3929. {
  3930. szdwFlags = "";
  3931. }
  3932. szdwFlags+="ELEMCHNG_REMEASUREINPARENT";
  3933. }
  3934. if ( pCAAI->dwFlags & CCSSF_SIZECHANGED )
  3935. {
  3936. // Always add dwFlags:ELEMCHNG_SIZECHANGED for these properties
  3937. if ( szdwFlags [0] )
  3938. {
  3939. szdwFlags += "|";
  3940. }
  3941. else
  3942. {
  3943. szdwFlags = "";
  3944. }
  3945. szdwFlags+="ELEMCHNG_SIZECHANGED";
  3946. }
  3947. }
  3948. else if ( pChild->IsSet ( PROPERTY_MEMBER ) )
  3949. {
  3950. // On the object
  3951. szMemberDesc = szClass;
  3952. szMemberDesc += ", ";
  3953. szMemberDesc += pChild->GetTagValue ( PROPERTY_MEMBER );
  3954. }
  3955. if ( pChild -> IsSet ( PROPERTY_ACCESSIBILITYSTATE) )
  3956. {
  3957. // we should only allow this on properties that can be set,
  3958. if ( ! ( pChild->IsSet ( PROPERTY_SET ) ) )
  3959. {
  3960. ReportError ( "Accessibility State can only be applied to r/w properties\n" );
  3961. return FALSE;
  3962. }
  3963. if ( szdwFlags [ 0 ] )
  3964. {
  3965. szdwFlags += "|";
  3966. }
  3967. szdwFlags += "ELEMCHNG_ACCESSIBILITY";
  3968. }
  3969. if ( pChild -> IsSet ( PROPERTY_UPDATECOLLECTION ) )
  3970. {
  3971. if ( szdwFlags [ 0 ] )
  3972. {
  3973. szdwFlags += "|";
  3974. }
  3975. szdwFlags += "ELEMCHNG_UPDATECOLLECTION";
  3976. }
  3977. if ( pChild -> IsSet ( PROPERTY_CLEARCACHES ) )
  3978. {
  3979. if ( szdwFlags [ 0 ] )
  3980. {
  3981. szdwFlags += "|";
  3982. }
  3983. szdwFlags += "ELEMCHNG_CLEARCACHES";
  3984. }
  3985. if ( pChild -> IsSet ( PROPERTY_STYLEPROP ) )
  3986. {
  3987. if ( szPropParamDesc [ 0 ] )
  3988. szPropParamDesc += " | ";
  3989. szPropParamDesc += "PROPPARAM_STYLESHEET_PROPERTY";
  3990. }
  3991. if ( pChild -> IsSet ( PROPERTY_DONTUSENOTASSIGN ) )
  3992. {
  3993. if ( szPropParamDesc [ 0 ] )
  3994. szPropParamDesc += " | ";
  3995. szPropParamDesc += "PROPPARAM_DONTUSENOTASSIGNED";
  3996. }
  3997. if ( pChild -> IsSet ( PROPERTY_RESIZE ) )
  3998. {
  3999. if ( szdwFlags [ 0 ] )
  4000. {
  4001. szdwFlags += "|";
  4002. }
  4003. szdwFlags += "ELEMCHNG_SIZECHANGED";
  4004. }
  4005. if ( pChild -> IsSet ( PROPERTY_REMEASURE ) )
  4006. {
  4007. if ( szdwFlags [ 0 ] )
  4008. {
  4009. szdwFlags += "|";
  4010. }
  4011. szdwFlags += "ELEMCHNG_REMEASURECONTENTS";
  4012. }
  4013. if ( pChild -> IsSet ( PROPERTY_REMEASUREALL ) )
  4014. {
  4015. if ( szdwFlags [ 0 ] )
  4016. {
  4017. szdwFlags += "|";
  4018. }
  4019. szdwFlags += "ELEMCHNG_REMEASUREALLCONTENTS";
  4020. }
  4021. if ( pChild -> IsSet ( PROPERTY_SITEREDRAW ) )
  4022. {
  4023. if ( szdwFlags [ 0 ] )
  4024. {
  4025. szdwFlags += "|";
  4026. }
  4027. szdwFlags += "ELEMCHNG_SITEREDRAW";
  4028. }
  4029. char szPropertyDesc [ MAX_LINE_LEN+1 ] ;
  4030. pChild -> GetTagValueOrDefault ( szNotPresentDefault, PROPERTY_NOTPRESENTDEFAULT, "0" );
  4031. if ( pChild->IsSet( PROPERTY_NOTPRESENTDEFAULT ) && szHandler == "String")
  4032. {
  4033. szNotPresentDefault = szPreText + szNotPresentDefault;
  4034. szNotPresentDefault += szPostText;
  4035. }
  4036. else if ( szHandler == "Color" && szNotPresentDefault == "0" )
  4037. {
  4038. // This is a nasty little hack to make for colors
  4039. szNotPresentDefault = "-1";
  4040. }
  4041. // If there's a not assigned default, use it, else use the not present default
  4042. pChild -> GetTagValueOrDefault ( szNotAssignedDefault, PROPERTY_NOTSETDEFAULT,
  4043. (LPCSTR)szNotPresentDefault );
  4044. if ( pChild->IsSet( PROPERTY_NOTSETDEFAULT ) && szHandler == "String")
  4045. {
  4046. szNotAssignedDefault = szPreText + szNotAssignedDefault;
  4047. szNotAssignedDefault += szPostText;
  4048. }
  4049. else if ( szHandler == "Color" && szNotAssignedDefault == "0" )
  4050. {
  4051. szNotAssignedDefault = "-1";
  4052. }
  4053. // szAttribute spevcifies the html name of the property, if not specified the
  4054. // property name itself is used.
  4055. if ( pChild -> IsSet ( PROPERTY_SZATTRIBUTE ) )
  4056. {
  4057. szHTMLName = pChild -> GetTagValue ( PROPERTY_SZATTRIBUTE );
  4058. sprintf ( (LPSTR) szExposedName,
  4059. "_T(\"%s\")",
  4060. pChild->GetTagValue ( PROPERTY_NAME ) );
  4061. }
  4062. else
  4063. {
  4064. szHTMLName = pChild -> GetTagValue ( PROPERTY_NAME );
  4065. strcpy(szExposedName, "NULL");
  4066. }
  4067. // If the propdesc has a member specified generate a full propdesc
  4068. // By setting abstract: AND member: the propdesc can be used for validation
  4069. // ( e.g. UnitMeasurement sub-object )
  4070. if ( pChild->IsSet ( PROPERTY_ABSTRACT ) && !pChild->IsSet ( PROPERTY_MEMBER ) )
  4071. {
  4072. // Generate a minimal propdesc, this is how IDispatchEx traverses
  4073. // attributes and properties.
  4074. sprintf ( (LPSTR) szPropertyDesc,
  4075. " s_propdesc%s%s = \n{\n NULL, _T(\"%s\"), %s, (ULONG_PTR)%s, (ULONG_PTR)%s,\n {",
  4076. (LPCSTR)szClass,
  4077. (LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ),
  4078. (LPCSTR)szHTMLName,
  4079. (LPCSTR)szExposedName,
  4080. (LPCSTR)szNotPresentDefault,
  4081. (LPCSTR)szNotAssignedDefault);
  4082. }
  4083. else
  4084. {
  4085. // If you're gonna set up a handler, better be a valid one
  4086. if ( szHandler == "" )
  4087. {
  4088. sprintf ( szErrorText, "Invalid Type:%s in Class:%s Property:%s\n",
  4089. (LPCSTR)pChild->GetTagValue ( PROPERTY_TYPE ),
  4090. (LPCSTR)pClassToken->GetTagValue(CLASS_NAME),
  4091. (LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ) );
  4092. ReportError ( szErrorText );
  4093. return FALSE;
  4094. }
  4095. char szTempBuf[MAX_LINE_LEN+1];
  4096. 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",
  4097. (LPCSTR)szClass,
  4098. (LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ),
  4099. (LPCSTR)szHandler,
  4100. (LPCSTR)szHTMLName,
  4101. (LPCSTR)szExposedName,
  4102. (LPCSTR)szNotPresentDefault,
  4103. (LPCSTR)szNotAssignedDefault);
  4104. sprintf ( (LPSTR) szPropertyDesc, "%s PROPERTYDESC::Handle%sProperty, _T(\"%s\"), %s, (ULONG_PTR)%s,(ULONG_PTR)%s,\n#endif\n {", szTempBuf,
  4105. (LPCSTR)szHandler,
  4106. (LPCSTR)szHTMLName,
  4107. (LPCSTR)szExposedName,
  4108. (LPCSTR)szNotPresentDefault,
  4109. (LPCSTR)szNotAssignedDefault);
  4110. }
  4111. if ( !ComputePROPDESC_STRUCT ( fpHDLFile, pClassToken, pChild, szHandler, szFnPrefix) )
  4112. return FALSE; // Bad error reported...leave
  4113. if ( !szdwFlags [ 0 ] )
  4114. szdwFlags = "0";
  4115. fNumericHandler = FALSE;
  4116. if ( !pChild->IsSet ( PROPERTY_ABSTRACT ) && szHandler == "Num" || szHandler == "Enum" || szHandler == "UnitValue" )
  4117. {
  4118. // Numeric Handlers
  4119. fNumericHandler = TRUE;
  4120. fprintf ( fpHDLFile, "%s\n {", szPropertyDesc );
  4121. if ( szHandler == "Enum" )
  4122. {
  4123. szPropParamDesc += " | PROPPARAM_ENUM";
  4124. }
  4125. else if ( pChild -> IsSet ( PROPERTY_ENUMREF ) )
  4126. {
  4127. // A number with one or more enums
  4128. szPropParamDesc += " | PROPPARAM_ENUM | PROPPARAM_ANUMBER";
  4129. }
  4130. pChild -> GetTagValueOrDefault ( szDispid, PROPERTY_DISPID, "0" );
  4131. if ((strcmp(pChild->GetTagValue(PROPERTY_ATYPE), "BSTR") == 0 || strcmp(pChild->GetTagValue(PROPERTY_ATYPE), "VARIANT") == 0) &&
  4132. ((pChild->IsSet(PROPERTY_CAA) || pChild->IsSet(PROPERTY_SET)) && !pChild->IsSet(PROPERTY_INTERNAL)) ||
  4133. (!pChild->IsSet(PROPERTY_CAA) && !pChild->IsSet(PROPERTY_SET) && !pChild->IsSet(PROPERTY_GET)))
  4134. {
  4135. if (!pChild->IsSet(PROPERTY_MAXSTRLEN))
  4136. {
  4137. char szErrorText [ MAX_LINE_LEN+1 ];
  4138. // Dispid not specified this is an error all methods should be accessible
  4139. // from automation.
  4140. sprintf ( szErrorText, "maxstrlen required for property: %s::%s in %s.\n",
  4141. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  4142. (LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ),
  4143. _pszPDLFileName );
  4144. ReportError ( szErrorText );
  4145. return FALSE;
  4146. }
  4147. }
  4148. else if (pChild->IsSet(PROPERTY_MAXSTRLEN))
  4149. {
  4150. char szErrorText [ MAX_LINE_LEN+1 ];
  4151. // Dispid not specified this is an error all methods should be accessible
  4152. // from automation.
  4153. sprintf ( szErrorText, "maxstrlen NOT required for property: %s::%s in %s.\n",
  4154. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  4155. (LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ),
  4156. _pszPDLFileName );
  4157. ReportError ( szErrorText );
  4158. return FALSE;
  4159. }
  4160. fprintf ( fpHDLFile, "\n %s, %s, %s, %s, %s \n },",
  4161. (LPCSTR)szPropParamDesc,
  4162. (LPCSTR)szDispid,
  4163. (LPCSTR)szdwFlags,
  4164. (LPCSTR)&chCustomInvokeIdx[0],
  4165. pChild->IsSet(PROPERTY_MAXSTRLEN) ? (LPCSTR)pChild->GetTagValue(PROPERTY_MAXSTRLEN) : "0");
  4166. if (fpMaxLenFile && pChild->IsSet(PROPERTY_MAXSTRLEN))
  4167. {
  4168. fprintf ( fpMaxLenFile, "%s::%s %s\n",
  4169. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  4170. (LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ),
  4171. (LPCSTR)pChild->GetTagValue(PROPERTY_MAXSTRLEN) );
  4172. }
  4173. if ( pChild->IsSet ( PROPERTY_ABSTRACT ) )
  4174. {
  4175. fprintf ( fpHDLFile, "\n 0, 0" );
  4176. }
  4177. else
  4178. {
  4179. if ( !pChild->IsSet ( PROPERTY_VT ) )
  4180. {
  4181. CString szAType;
  4182. szAType = pChild->GetTagValue ( PROPERTY_ATYPE );
  4183. if ( szAType == "short" || szAType == "VARIANT_BOOL" )
  4184. szVTDef = "VT_I2";
  4185. else
  4186. szVTDef = "VT_I4";
  4187. }
  4188. else
  4189. {
  4190. szVTDef = pChild->GetTagValue ( PROPERTY_VT );
  4191. }
  4192. if ( pChild -> IsSet ( PROPERTY_GETSETMETHODS ) )
  4193. {
  4194. fprintf ( fpHDLFile, "\n %s, 0",
  4195. (LPCSTR)szVTDef );
  4196. }
  4197. else if ( pChild -> IsSet ( PROPERTY_CAA ) )
  4198. {
  4199. fprintf ( fpHDLFile, "\n %s, sizeof(DWORD)",
  4200. (LPCSTR)szVTDef );
  4201. }
  4202. else
  4203. {
  4204. fprintf ( fpHDLFile, "\n %s, SIZE_OF(%s)",
  4205. (LPCSTR)szVTDef, (LPCSTR)szMemberDesc );
  4206. }
  4207. }
  4208. // Fill in the min/max values
  4209. // If it's an enum, the min value is a ptr to the enum desc structure
  4210. if ( szHandler == "Enum" )
  4211. {
  4212. if ( pChild->IsSet ( PROPERTY_ABSTRACT ) )
  4213. {
  4214. fprintf ( fpHDLFile, ", 0, 0,\n" );
  4215. }
  4216. else
  4217. {
  4218. // Get the enum mask from the enum named by PROPERTY_TYPE
  4219. CTokenListWalker WholeList ( pRuntimeList );
  4220. Token *pEnumToken = WholeList.GetNext ( TYPE_ENUM, pChild->GetTagValue ( PROPERTY_TYPE ) );
  4221. CString szMin;
  4222. pChild->GetTagValueOrDefault ( szMin, PROPERTY_MIN, "0" );
  4223. if ( pEnumToken == NULL )
  4224. {
  4225. sprintf ( szErrorText,
  4226. "unknown enum type %s\n",pChild->GetTagValue ( PROPERTY_TYPE ) );
  4227. ReportError ( szErrorText );
  4228. return FALSE;
  4229. }
  4230. fprintf ( fpHDLFile, ", %s, (LONG_PTR)&s_enumdesc%s,\n",
  4231. (LPCSTR)szMin, pChild->GetTagValue ( PROPERTY_TYPE ) );
  4232. }
  4233. }
  4234. else
  4235. {
  4236. CString szMax;
  4237. CString szMin;
  4238. pChild->GetTagValueOrDefault ( szMin, PROPERTY_MIN, "LONG_MIN" );
  4239. pChild->GetTagValueOrDefault ( szMax, PROPERTY_MAX, "LONG_MAX" );
  4240. fprintf ( fpHDLFile, ", %s, %s,\n", (LPCSTR)szMin, (LPCSTR)szMax );
  4241. }
  4242. }
  4243. else
  4244. {
  4245. fprintf ( fpHDLFile, "%s\n ", szPropertyDesc );
  4246. pChild -> GetTagValueOrDefault ( szDispid, PROPERTY_DISPID, "0" );
  4247. if ((strcmp(pChild->GetTagValue(PROPERTY_ATYPE), "BSTR") == 0 || strcmp(pChild->GetTagValue(PROPERTY_ATYPE), "VARIANT") == 0) &&
  4248. ((pChild->IsSet(PROPERTY_CAA) || pChild->IsSet(PROPERTY_SET)) && !pChild->IsSet(PROPERTY_INTERNAL)) ||
  4249. (!pChild->IsSet(PROPERTY_CAA) && !pChild->IsSet(PROPERTY_SET) && !pChild->IsSet(PROPERTY_GET)))
  4250. {
  4251. if (!pChild->IsSet(PROPERTY_MAXSTRLEN))
  4252. {
  4253. char szErrorText [ MAX_LINE_LEN+1 ];
  4254. // Dispid not specified this is an error all methods should be accessible
  4255. // from automation.
  4256. sprintf ( szErrorText, "maxstrlen required for property: %s::%s in %s.\n",
  4257. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  4258. (LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ),
  4259. _pszPDLFileName );
  4260. ReportError ( szErrorText );
  4261. return FALSE;
  4262. }
  4263. }
  4264. else if (pChild->IsSet(PROPERTY_MAXSTRLEN))
  4265. {
  4266. char szErrorText [ MAX_LINE_LEN+1 ];
  4267. // Dispid not specified this is an error all methods should be accessible
  4268. // from automation.
  4269. sprintf ( szErrorText, "maxstrlen NOT required for property: %s::%s in %s.\n",
  4270. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  4271. (LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ),
  4272. _pszPDLFileName );
  4273. ReportError ( szErrorText );
  4274. return FALSE;
  4275. }
  4276. fprintf ( fpHDLFile, " %s, %s, %s, %s, %s \n",
  4277. (LPCSTR)szPropParamDesc,
  4278. (LPCSTR)szDispid,
  4279. (LPCSTR)szdwFlags,
  4280. (LPCSTR)&chCustomInvokeIdx[0],
  4281. pChild->IsSet(PROPERTY_MAXSTRLEN) ? (LPCSTR)pChild->GetTagValue(PROPERTY_MAXSTRLEN) : "0");
  4282. if (fpMaxLenFile && pChild->IsSet(PROPERTY_MAXSTRLEN))
  4283. {
  4284. fprintf ( fpMaxLenFile, "%s::%s %s\n",
  4285. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  4286. (LPCSTR)pChild->GetTagValue ( PROPERTY_NAME ),
  4287. (LPCSTR)pChild->GetTagValue(PROPERTY_MAXSTRLEN) );
  4288. }
  4289. }
  4290. fprintf ( fpHDLFile, " }," );
  4291. if (pEventChild && pChild->IsSet(PROPERTY_SCRIPTLET))
  4292. {
  4293. fprintf(fpHDLFile, "\n (DWORD_PTR)%s", pEventChild->GetTagValue(METHOD_DISPID));
  4294. }
  4295. else if ( pChild->IsSet ( PROPERTY_GETSETMETHODS ) )
  4296. {
  4297. fprintf ( fpHDLFile, "\n PROPERTY_METHOD(%s, GET, %s, Get%s, GET%s)," ,
  4298. (LPCSTR)szFnPrefix,
  4299. (LPCSTR)szClass, (LPCSTR)pChild->GetTagValue ( PROPERTY_GETSETMETHODS ),
  4300. (LPCSTR)pChild->GetTagValue ( PROPERTY_GETSETMETHODS ));
  4301. fprintf ( fpHDLFile, "\n PROPERTY_METHOD(%s, SET, %s, Set%s, SET%s)" ,
  4302. (LPCSTR)szFnPrefix,
  4303. (LPCSTR)szClass, (LPCSTR)pChild->GetTagValue ( PROPERTY_GETSETMETHODS ),
  4304. (LPCSTR)pChild->GetTagValue ( PROPERTY_GETSETMETHODS ));
  4305. }
  4306. else if ( pChild->IsSet ( PROPERTY_ABSTRACT ) )
  4307. {
  4308. }
  4309. else if ( szMemberDesc [ 0 ] )
  4310. {
  4311. fprintf ( fpHDLFile, "\n offsetof(%s)",
  4312. (LPCSTR)szMemberDesc );
  4313. }
  4314. if ( fNumericHandler && pChild->IsSet ( PROPERTY_ENUMREF ) &&
  4315. !pChild->IsSet ( PROPERTY_ABSTRACT ) )
  4316. {
  4317. CTokenListWalker WholeList ( pRuntimeList );
  4318. Token *pEnumToken = WholeList.GetNext ( TYPE_ENUM,
  4319. pChild->GetTagValue ( PROPERTY_ENUMREF ) );
  4320. if ( pEnumToken == NULL )
  4321. {
  4322. sprintf ( szErrorText,
  4323. "unknown enum type %s\n",pChild->GetTagValue ( PROPERTY_ENUMREF ) );
  4324. ReportError ( szErrorText );
  4325. return FALSE;
  4326. }
  4327. if ( !szMemberDesc [ 0 ] )
  4328. {
  4329. fprintf ( fpHDLFile, "\n 0, &s_enumdesc%s",
  4330. pChild->GetTagValue ( PROPERTY_ENUMREF ) );
  4331. }
  4332. else
  4333. {
  4334. fprintf ( fpHDLFile, "\n &s_enumdesc%s",
  4335. pChild->GetTagValue ( PROPERTY_ENUMREF ) );
  4336. }
  4337. }
  4338. fprintf ( fpHDLFile, "\n};\n\n" );
  4339. return TRUE;
  4340. }
  4341. BOOL CPDLParser::BuildMethodSignature(Token *pChild,
  4342. CString &szTypesSig,
  4343. CString &szArgsType,
  4344. BOOL &fBSTRArg,
  4345. BOOL &fVARIANTArg,
  4346. int &cArgs,
  4347. int &cRequiredArgs,
  4348. char *pDefaultParams[MAX_ARGS],
  4349. char *pDefaultStrParams[MAX_ARGS])
  4350. {
  4351. Token *pArgToken;
  4352. CTokenListWalker ArgListWalker(pChild);
  4353. char *pDispatchType;
  4354. char szErrorText [ MAX_LINE_LEN+1 ];
  4355. cArgs = 0;
  4356. cRequiredArgs = 0;
  4357. fBSTRArg = FALSE;
  4358. fVARIANTArg = FALSE;
  4359. // Loop thru all arguments.
  4360. while ( (pArgToken = ArgListWalker.GetNext()) != NULL &&
  4361. pArgToken -> GetType () == TYPE_METHOD_ARG )
  4362. {
  4363. fBSTRArg |= (strcmp(pArgToken->GetTagValue(METHODARG_TYPE), "BSTR") == 0);
  4364. fVARIANTArg |= (!pArgToken->IsSet(METHODARG_OUT) && (strcmp(pArgToken->GetTagValue(METHODARG_TYPE), "VARIANT") == 0 || strcmp(pArgToken->GetTagValue(METHODARG_TYPE), "VARIANT*") == 0));
  4365. // Looking for a return value.
  4366. if ( pArgToken -> IsSet ( METHODARG_RETURNVALUE ) )
  4367. {
  4368. char *pWS;
  4369. szTypesSig = pArgToken -> GetTagValue ( METHODARG_TYPE );
  4370. // Remove any underscores in the type name.
  4371. while ((pWS = szTypesSig.FindChar('_')))
  4372. {
  4373. while (*pWS = *(pWS + 1))
  4374. pWS++;
  4375. *pWS = '\0';
  4376. }
  4377. // Should this type be mapped to IDispatch?
  4378. pDispatchType = MapTypeToIDispatch ( szTypesSig );
  4379. if (pDispatchType)
  4380. {
  4381. szTypesSig = pDispatchType;
  4382. }
  4383. }
  4384. else
  4385. {
  4386. CString szArg;
  4387. char *pWS;
  4388. if ( pArgToken->IsSet ( METHODARG_OPTIONAL ) )
  4389. {
  4390. // little o + zero + little o, prepended to the type signals
  4391. // the type is optional.
  4392. szArg = "o0o";
  4393. }
  4394. if ( pArgToken -> IsSet ( METHODARG_DEFAULTVALUE ) )
  4395. {
  4396. // Signal default.
  4397. szArg = "oDo";
  4398. if (cArgs >= MAX_ARGS)
  4399. {
  4400. sprintf ( szErrorText, "PDL parser can only handle upto 8 parameters (increase MAX_ARGS) %s in file %s.\n",
  4401. (LPCSTR)pChild->GetTagValue ( METHOD_NAME ),
  4402. _pszPDLFileName );
  4403. ReportError ( szErrorText );
  4404. return FALSE;
  4405. }
  4406. // Currently I only handle 2 types of default values numbers and
  4407. // strings. If any other appear then I'll need to add those as
  4408. // well.
  4409. if ( strcmp (pArgToken -> GetTagValue ( METHODARG_TYPE ), "BSTR") == 0)
  4410. {
  4411. if (pDefaultStrParams)
  4412. pDefaultStrParams[cArgs] = pArgToken -> GetTagValue ( METHODARG_DEFAULTVALUE );
  4413. }
  4414. else if (pDefaultParams)
  4415. {
  4416. pDefaultParams[cArgs] = pArgToken -> GetTagValue ( METHODARG_DEFAULTVALUE );
  4417. }
  4418. }
  4419. else
  4420. {
  4421. // If not optional and not defaultValue then the argument is
  4422. // required and no defaults could have appeared in between.
  4423. if ( !pArgToken->IsSet ( METHODARG_OPTIONAL ) )
  4424. {
  4425. // Insure that once a default argument is hit all arguments from
  4426. // that point to the last argument im the function are either
  4427. // defaultValue or optional.
  4428. if (cRequiredArgs != cArgs)
  4429. {
  4430. sprintf ( szErrorText, "Default arguments must be contiguous to last argument %s in file %s.\n",
  4431. (LPCSTR)pChild->GetTagValue ( METHOD_NAME ),
  4432. _pszPDLFileName );
  4433. ReportError ( szErrorText );
  4434. return FALSE;
  4435. }
  4436. // Arguments without a defaultValue/optional are required args.
  4437. // Unless the argument is a safe array than any number of
  4438. // arguments can be specified 0 to n arguments
  4439. if (strcmp((LPCSTR)(pArgToken -> GetTagValue(METHODARG_TYPE)), "SAFEARRAY(VARIANT)") != 0)
  4440. // Not a safearray so it's a required argument.
  4441. cRequiredArgs++;
  4442. }
  4443. }
  4444. szArg += pArgToken -> GetTagValue ( METHODARG_TYPE );
  4445. if (szArg == "oDoVARIANT")
  4446. {
  4447. sprintf ( szErrorText, "Default arguments cannot be VARIANT %s in file %s.\n",
  4448. (LPCSTR)pChild->GetTagValue ( METHOD_NAME ),
  4449. _pszPDLFileName );
  4450. ReportError ( szErrorText );
  4451. return FALSE;
  4452. }
  4453. if ( pArgToken->IsSet ( METHODARG_OPTIONAL ) &&
  4454. !(szArg == "o0oVARIANT" || szArg == "o0oVARIANT*") )
  4455. {
  4456. sprintf ( szErrorText, "Optional arguments can ONLY be VARIANT or VARIANT* %s in file %s.\n",
  4457. (LPCSTR)pChild->GetTagValue ( METHOD_NAME ),
  4458. _pszPDLFileName );
  4459. ReportError ( szErrorText );
  4460. return FALSE;
  4461. }
  4462. // Should this type be mapped to IDispatch?
  4463. pDispatchType = MapTypeToIDispatch ( szArg );
  4464. if (pDispatchType)
  4465. {
  4466. // Remap to IDispatch* or IDispatch**
  4467. szArg = pDispatchType;
  4468. }
  4469. cArgs++;
  4470. // Remove any underscores in the type name.
  4471. while ((pWS = szArg.FindChar('_')))
  4472. {
  4473. while (*pWS = *(pWS + 1))
  4474. pWS++;
  4475. *pWS = '\0';
  4476. }
  4477. szArgsType += "_";
  4478. szArgsType += (LPCSTR)szArg;
  4479. }
  4480. }
  4481. return TRUE;
  4482. }
  4483. BOOL CPDLParser::ComputeMethod ( Token *pClassToken, Token *pChild )
  4484. {
  4485. CString szTypesSig;
  4486. CString szArgsType;
  4487. CString szDispid;
  4488. CTokenListWalker ArgListWalker ( pChild );
  4489. char chCustomInvokeIdx[128];
  4490. int cArgs = 0;
  4491. int cRequiredArgs = 0;
  4492. char szErrorText [ MAX_LINE_LEN+1 ];
  4493. char *pDefaultParams[MAX_ARGS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
  4494. char *pDefaultStrParams[MAX_ARGS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
  4495. BOOL fBSTRArg;
  4496. BOOL fVARIANTArg;
  4497. if (!BuildMethodSignature(pChild,
  4498. szTypesSig,
  4499. szArgsType,
  4500. fBSTRArg,
  4501. fVARIANTArg,
  4502. cArgs,
  4503. cRequiredArgs,
  4504. pDefaultParams,
  4505. pDefaultStrParams))
  4506. return FALSE;
  4507. // Any default values?
  4508. if (cArgs != cRequiredArgs)
  4509. {
  4510. int i;
  4511. // Spit out any default string constants.
  4512. for ( i = cRequiredArgs; i < cArgs; i++)
  4513. {
  4514. if ( pDefaultStrParams[i] )
  4515. {
  4516. fprintf ( fpHDLFile, "const TCHAR s_strDef%s%s%i[] = _T(%s);\n",
  4517. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  4518. (LPCSTR)pChild->GetTagValue ( METHOD_NAME ),
  4519. i - cRequiredArgs,
  4520. pDefaultStrParams[i] );
  4521. }
  4522. }
  4523. fprintf ( fpHDLFile, "const DEFAULTARGDESC s_defArg%s%s =\n{\n",
  4524. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  4525. (LPCSTR)pChild->GetTagValue ( METHOD_NAME ) );
  4526. // Spit out the all of all default constants
  4527. for ( i = cRequiredArgs; i < cArgs; i++)
  4528. {
  4529. if ( pDefaultStrParams[i] )
  4530. {
  4531. fprintf ( fpHDLFile, " (DWORD_PTR)s_strDef%s%s%i,\n",
  4532. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  4533. (LPCSTR)pChild->GetTagValue ( METHOD_NAME ),
  4534. i - cRequiredArgs );
  4535. }
  4536. else
  4537. {
  4538. fprintf ( fpHDLFile, " (DWORD_PTR)%s,\n", pDefaultParams[i] ? pDefaultParams[i] : "\"\"" );
  4539. }
  4540. }
  4541. fprintf ( fpHDLFile, "};\n" );
  4542. }
  4543. // If no return value then set the retVal to void.
  4544. if (!szTypesSig[0])
  4545. {
  4546. szTypesSig = "void";
  4547. }
  4548. // If no arguments then set the argList to void.
  4549. if (!szArgsType[0])
  4550. {
  4551. szArgsType = "_void";
  4552. }
  4553. szTypesSig += szArgsType;
  4554. szDispid = pChild->GetTagValue(METHOD_DISPID);
  4555. if (szDispid[0])
  4556. {
  4557. // Write out the function signature for this method
  4558. // only do this if a dispid exists. Methods without dispid
  4559. // are not accessible through automation.
  4560. if ( !FindAndAddSignature ( "Method", szTypesSig, &chCustomInvokeIdx[0] ) )
  4561. return FALSE;
  4562. }
  4563. fprintf ( fpHDLFile, "EXTERN_C const PROPERTYDESC_METHOD s_methdesc%s%s = \n{\n",
  4564. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  4565. (LPCSTR)pChild->GetTagValue ( METHOD_NAME ));
  4566. fprintf ( fpHDLFile, " NULL, NULL, _T(\"%s\"), (ULONG)0, (ULONG)0,\n {\n",
  4567. (LPCSTR)pChild->GetTagValue ( METHOD_NAME ));
  4568. if (!szDispid[0])
  4569. {
  4570. // Dispid not specified this is an error all methods should be accessible
  4571. // from automation.
  4572. sprintf ( szErrorText, "DISPID required for method: %s::%s in %s.\n",
  4573. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  4574. (LPCSTR)pChild->GetTagValue ( METHOD_NAME ),
  4575. _pszPDLFileName );
  4576. ReportError ( szErrorText );
  4577. return FALSE;
  4578. }
  4579. if (fBSTRArg || fVARIANTArg)
  4580. {
  4581. if (!pChild->IsSet(METHOD_MAXSTRLEN))
  4582. {
  4583. // Dispid not specified this is an error all methods should be accessible
  4584. // from automation.
  4585. sprintf ( szErrorText, "maxstrlen required for method: %s::%s in %s.\n",
  4586. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  4587. (LPCSTR)pChild->GetTagValue ( METHOD_NAME ),
  4588. _pszPDLFileName );
  4589. ReportError ( szErrorText );
  4590. return FALSE;
  4591. }
  4592. }
  4593. else if (pChild->IsSet(METHOD_MAXSTRLEN))
  4594. {
  4595. // Dispid not specified this is an error all methods should be accessible
  4596. // from automation.
  4597. sprintf ( szErrorText, "maxstrlen NOT required for method: %s::%s in %s.\n",
  4598. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  4599. (LPCSTR)pChild->GetTagValue ( METHOD_NAME ),
  4600. _pszPDLFileName );
  4601. ReportError ( szErrorText );
  4602. return FALSE;
  4603. }
  4604. fprintf ( fpHDLFile, " %s, %s, 0, %s, %s\n },\n ",
  4605. pChild->IsSet(METHOD_RESTRICTED) ? "PROPPARAM_RESTRICTED" : "0",
  4606. (LPCSTR)szDispid,
  4607. (LPCSTR)&chCustomInvokeIdx[0],
  4608. pChild->IsSet(METHOD_MAXSTRLEN) ? (LPCSTR)pChild->GetTagValue(METHOD_MAXSTRLEN) : "0");
  4609. if (fpMaxLenFile && pChild->IsSet(METHOD_MAXSTRLEN))
  4610. {
  4611. fprintf ( fpMaxLenFile, "%s::%s %s\n",
  4612. (LPCSTR)pClassToken->GetTagValue(CLASS_NAME),
  4613. (LPCSTR)pChild->GetTagValue(METHOD_NAME),
  4614. (LPCSTR)pChild->GetTagValue(METHOD_MAXSTRLEN) );
  4615. }
  4616. if ( cArgs != cRequiredArgs )
  4617. {
  4618. fprintf ( fpHDLFile, "&s_defArg%s%s, ",
  4619. (LPCSTR)pClassToken->GetTagValue ( CLASS_NAME ),
  4620. (LPCSTR)pChild->GetTagValue ( METHOD_NAME ) );
  4621. }
  4622. else
  4623. {
  4624. fprintf ( fpHDLFile, "NULL, " );
  4625. }
  4626. fprintf ( fpHDLFile, "%i, %i\n};\n\n",
  4627. cArgs,
  4628. cRequiredArgs );
  4629. return TRUE;
  4630. }
  4631. BOOL CPDLParser::GeneratePROPDESCs ( void )
  4632. {
  4633. Token *pClassToken;
  4634. Token *pChild;
  4635. // Only generate def's for this file
  4636. CTokenListWalker TokenList ( pRuntimeList, _pszPDLFileName );
  4637. // Generate propdescs for every property token in every class ( in this file )
  4638. while ( pClassToken = TokenList.GetNext( TYPE_CLASS ) )
  4639. {
  4640. fprintf ( fpHDLFile, "\n" );
  4641. CTokenListWalker ChildList ( pClassToken );
  4642. // if ( pClassToken -> IsSet ( CLASS_ABSTRACT ) )
  4643. // {
  4644. // fprintf ( fpHDLFile, "\n#ifndef _PROPDESCS_EXTERNAL\n" );
  4645. // }
  4646. fprintf ( fpHDLFile, "\n#define _%s_PROPDESCS_\n", pClassToken -> GetTagValue ( CLASS_NAME ) );
  4647. // Walk the super class propdescs looking for properties
  4648. while ( pChild = ChildList.GetNext() )
  4649. {
  4650. if ( pChild->nType == TYPE_PROPERTY &&
  4651. _stricmp(pChild->GetTagValue(PROPERTY_NOPROPDESC), "nameonly") != 0 )
  4652. {
  4653. if ( !ComputeProperty ( pClassToken, pChild ) )
  4654. return FALSE;
  4655. }
  4656. else if ( pChild->nType == TYPE_METHOD && !pChild->IsSet(METHOD_NOPROPDESC))
  4657. {
  4658. if (!ComputeMethod(pClassToken, pChild) )
  4659. return FALSE;
  4660. }
  4661. else
  4662. {
  4663. continue;
  4664. }
  4665. }
  4666. if (fpMaxLenFile)
  4667. fprintf(fpMaxLenFile, "\n");
  4668. }
  4669. return TRUE;
  4670. }
  4671. void CPDLParser::GenerateThunkContext ( Token *pClassToken )
  4672. {
  4673. CTokenListWalker ChildList (pClassToken);
  4674. Token *pChildToken;
  4675. while (pChildToken = ChildList.GetNext())
  4676. {
  4677. if( (pChildToken->GetType() == TYPE_METHOD && pChildToken->IsSet(METHOD_THUNKCONTEXT)) ||
  4678. (pChildToken->GetType() == TYPE_PROPERTY && pChildToken->IsSet(PROPERTY_THUNKCONTEXT)) )
  4679. {
  4680. GenerateSingleThunkContextPrototype(pClassToken, pChildToken, FALSE);
  4681. }
  4682. if( (pChildToken->GetType() == TYPE_METHOD && pChildToken->IsSet(METHOD_THUNKNODECONTEXT)) ||
  4683. (pChildToken->GetType() == TYPE_PROPERTY && pChildToken->IsSet(PROPERTY_THUNKNODECONTEXT)) )
  4684. {
  4685. GenerateSingleThunkContextPrototype(pClassToken, pChildToken, TRUE);
  4686. }
  4687. }
  4688. }
  4689. void CPDLParser::GenerateSingleThunkContextPrototype ( Token *pClassToken, Token * pChildToken, BOOL fNodeContext )
  4690. {
  4691. CString szProp;
  4692. Token *pArgToken;
  4693. if (pChildToken->GetType() == TYPE_METHOD)
  4694. {
  4695. CTokenListWalker ArgListWalker(pChildToken);
  4696. BOOL fFirst = TRUE;
  4697. fprintf(fpHDLFile, " STDMETHODIMP %s(", (LPCSTR)pChildToken->GetTagValue(METHOD_NAME));
  4698. while (pArgToken = ArgListWalker.GetNext())
  4699. {
  4700. if (!fFirst)
  4701. fprintf(fpHDLFile, ",");
  4702. fprintf(fpHDLFile, "%s %s",
  4703. ConvertType((LPCSTR)pArgToken->GetTagValue ( METHODARG_TYPE )),
  4704. (LPCSTR)pArgToken -> GetTagValue ( METHODARG_ARGNAME ) );
  4705. fFirst = FALSE;
  4706. }
  4707. if(fNodeContext)
  4708. {
  4709. fprintf(fpHDLFile, "%sCTreeNode *pNode);\n", fFirst?"":",");
  4710. }
  4711. else
  4712. {
  4713. fprintf(fpHDLFile, "%sTEAROFF_THUNK*ptt);\n", fFirst?"":",");
  4714. }
  4715. }
  4716. else
  4717. {
  4718. if (pChildToken->IsSet(PROPERTY_SET))
  4719. {
  4720. fprintf(fpHDLFile, " STDMETHODIMP set_%s(%s v, %s);\n",
  4721. (LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME),
  4722. (LPCSTR)pChildToken -> GetTagValue(PROPERTY_ATYPE),
  4723. fNodeContext?"CTreeNode *pNode":"TEAROFF_THUNK *ptt");
  4724. }
  4725. if (pChildToken->IsSet(PROPERTY_GET))
  4726. {
  4727. fprintf(fpHDLFile, " STDMETHODIMP get_%s(%s *p, %s);\n",
  4728. (LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME),
  4729. (LPCSTR)pChildToken -> GetTagValue(PROPERTY_ATYPE),
  4730. fNodeContext?"CTreeNode *pNode":"TEAROFF_THUNK *ptt");
  4731. }
  4732. }
  4733. }
  4734. void CPDLParser::GenerateThunkContextImplemenation ( Token *pClassToken )
  4735. {
  4736. CTokenListWalker ChildList (pClassToken);
  4737. Token *pChildToken;
  4738. while (pChildToken = ChildList.GetNext())
  4739. {
  4740. if( (pChildToken->GetType() == TYPE_METHOD && pChildToken->IsSet(METHOD_THUNKCONTEXT)) ||
  4741. (pChildToken->GetType() == TYPE_PROPERTY && pChildToken->IsSet(PROPERTY_THUNKCONTEXT)) )
  4742. {
  4743. GenerateSingleThunkContextImplementation(pClassToken, pChildToken, FALSE);
  4744. }
  4745. if( (pChildToken->GetType() == TYPE_METHOD && pChildToken->IsSet(METHOD_THUNKNODECONTEXT)) ||
  4746. (pChildToken->GetType() == TYPE_PROPERTY && pChildToken->IsSet(PROPERTY_THUNKNODECONTEXT)) )
  4747. {
  4748. GenerateSingleThunkContextImplementation(pClassToken, pChildToken, TRUE);
  4749. }
  4750. }
  4751. }
  4752. void CPDLParser::GenerateSingleThunkContextImplementation ( Token *pClassToken, Token * pChildToken, BOOL fNodeContext )
  4753. {
  4754. CString szProp;
  4755. Token *pArgToken;
  4756. fprintf(fpHDLFile, "#ifdef USE_STACK_SPEW\n#pragma check_stack(off)\n#endif\n");
  4757. if (pChildToken->GetType() == TYPE_METHOD)
  4758. {
  4759. CTokenListWalker ArgListWalker(pChildToken);
  4760. BOOL fFirst = TRUE;
  4761. fprintf(fpHDLFile, "STDMETHODIMP %s::ContextThunk_%s(",
  4762. (LPCSTR)pClassToken->GetTagValue(CLASS_NAME),
  4763. (LPCSTR)pChildToken->GetTagValue(METHOD_NAME));
  4764. while (pArgToken = ArgListWalker.GetNext())
  4765. {
  4766. if (!fFirst)
  4767. fprintf(fpHDLFile, ",");
  4768. fprintf(fpHDLFile, "%s %s",
  4769. ConvertType((LPCSTR)pArgToken->GetTagValue ( METHODARG_TYPE )),
  4770. (LPCSTR)pArgToken -> GetTagValue ( METHODARG_ARGNAME ) );
  4771. fFirst = FALSE;
  4772. }
  4773. if(fNodeContext)
  4774. {
  4775. fprintf(fpHDLFile, ")\n"
  4776. "{\n"
  4777. " CTreeNode* pNode;\n"
  4778. " CONTEXTTHUNK_SETTREENODE\n"
  4779. " return %s(", (LPCSTR)pChildToken->GetTagValue(METHOD_NAME));
  4780. }
  4781. else
  4782. {
  4783. fprintf(fpHDLFile, ")\n"
  4784. "{\n"
  4785. " TEAROFF_THUNK* ptt;\n"
  4786. " CONTEXTTHUNK_SETTEAROFFTHUNK\n"
  4787. " return %s(", (LPCSTR)pChildToken->GetTagValue(METHOD_NAME));
  4788. }
  4789. fFirst = TRUE;
  4790. ArgListWalker.Reset();
  4791. while (pArgToken = ArgListWalker.GetNext())
  4792. {
  4793. if (!fFirst)
  4794. fprintf(fpHDLFile, ",");
  4795. fprintf(fpHDLFile, "%s",
  4796. (LPCSTR)pArgToken -> GetTagValue(METHODARG_ARGNAME));
  4797. fFirst = FALSE;
  4798. }
  4799. fprintf(fpHDLFile, "%s%s);\n}\n", fFirst?"":",", fNodeContext?"pNode":"ptt");
  4800. }
  4801. else
  4802. {
  4803. if (pChildToken->IsSet(PROPERTY_SET))
  4804. {
  4805. fprintf(fpHDLFile,
  4806. "STDMETHODIMP %s::ContextThunk_set_%s(%s v)\n"
  4807. "{\n%s return set_%s(v,%s);\n}\n",
  4808. (LPCSTR)pClassToken->GetTagValue(CLASS_NAME),
  4809. (LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME),
  4810. (LPCSTR)pChildToken->GetTagValue(PROPERTY_ATYPE),
  4811. fNodeContext
  4812. ? " CTreeNode* pNode;\n"
  4813. " CONTEXTTHUNK_SETTREENODE\n"
  4814. : " TEAROFF_THUNK* ptt;\n"
  4815. " CONTEXTTHUNK_SETCONTEXTTHUNK\n",
  4816. (LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME),
  4817. fNodeContext ? "pNode" : "ptt");
  4818. }
  4819. if (pChildToken->IsSet(PROPERTY_GET))
  4820. {
  4821. fprintf(fpHDLFile,
  4822. "STDMETHODIMP %s::ContextThunk_get_%s(%s *p)\n"
  4823. "{\n%s return get_%s(p,%s);\n}\n",
  4824. (LPCSTR)pClassToken->GetTagValue(CLASS_NAME),
  4825. (LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME),
  4826. (LPCSTR)pChildToken->GetTagValue(PROPERTY_ATYPE),
  4827. fNodeContext
  4828. ? " CTreeNode* pNode;\n"
  4829. " CONTEXTTHUNK_SETTREENODE\n"
  4830. : " TEAROFF_THUNK* ptt;\n"
  4831. " CONTEXTTHUNK_SETCONTEXTTHUNK\n",
  4832. (LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME),
  4833. fNodeContext ? "pNode" : "ptt");
  4834. }
  4835. }
  4836. fprintf(fpHDLFile, "#ifdef USE_STACK_SPEW\n#pragma check_stack(on)\n#endif\n");
  4837. }
  4838. BOOL CPDLParser::GenerateHDLFile ( void )
  4839. {
  4840. Token *pClassToken;
  4841. BOOL bHashTableExists;
  4842. int numVTblPropDescs;
  4843. CTokenListWalker ThisFilesList ( pRuntimeList, _pszPDLFileName );
  4844. fprintf ( fpHDLFile, "\n" );
  4845. fprintf ( fpHDLFile, "// %s.hdl\n", _pszOutputFileRoot );
  4846. fprintf ( fpHDLFile, "\n" );
  4847. fprintf ( fpHDLFile, "#ifdef _hxx_\n" );
  4848. fprintf ( fpHDLFile, "\n" );
  4849. fprintf ( fpHDLFile, "#include \"%s.h\"\n", _pszOutputFileRoot );
  4850. fprintf ( fpHDLFile, "\n" );
  4851. // Generate the DISPID's, one for each member of each class
  4852. fprintf ( fpLOGFile, "Generating DISPID's...\n" );
  4853. GenerateClassDISPIDs();
  4854. GenerateInterfaceDISPIDs();
  4855. GenerateEventDISPIDs( fpHDLFile, TRUE );
  4856. fprintf ( fpHDLFile, "\n" );
  4857. fprintf ( fpHDLFile, "#endif _hxx_\n" );
  4858. fprintf ( fpHDLFile, "\n" );
  4859. fprintf ( fpHDLFile, "#undef _hxx_\n" );
  4860. fprintf ( fpHDLFile, "\n" );
  4861. fprintf ( fpHDLFile, "#ifdef _cxx_\n" );
  4862. fprintf ( fpHDLFile, "\n" );
  4863. // Generate the enum definitions
  4864. fprintf ( fpLOGFile, "Generating CPP Enum Defs...\n" );
  4865. GenerateCPPEnumDefs();
  4866. // Generate the property descriptors
  4867. fprintf ( fpLOGFile, "Generating PROPDESC's...\n" );
  4868. if ( !GeneratePROPDESCs() )
  4869. goto Error;
  4870. #ifdef COMPLUS_SHIM
  4871. // ***TLL*** COM+: Not spitting COM+ proxies for internal.pdl and mshtmext.pdl need to do, shouldn't special case.
  4872. if ((_stricmp(_pszPDLFileName, "internal.pdl") != 0) && (_stricmp(_pszPDLFileName, "mshtmext.pdl") != 0))
  4873. {
  4874. GenComPlusESI(); // Output any local interfaces for COM+
  4875. }
  4876. #endif // COMPLUS_SHIM
  4877. // For each TYPE_CLASS in this file generate a propdesc array and vtable
  4878. // array for the class.
  4879. while ( pClassToken = ThisFilesList.GetNext( TYPE_CLASS ) )
  4880. {
  4881. // Generate propdescs for every property token in every class ( in this file )
  4882. fprintf ( fpLOGFile, "Generating PROPDESC Arrays...\n" );
  4883. if ( !GenerateCPC( pClassToken ) )
  4884. goto Error;
  4885. // Generate the vtable array for classes in this file
  4886. fprintf ( fpLOGFile, "Generating VTable Arrays...\n" );
  4887. GenerateVTableArray(pClassToken, &bHashTableExists);
  4888. // Generate the propdesc array in vtable order for classes in this file
  4889. fprintf ( fpLOGFile, "Generating propdesc Arrays in vtbl order...\n" );
  4890. GeneratePropDescsInVtblOrder(pClassToken, &numVTblPropDescs);
  4891. // Abstract classes don't have propdesc arrays or vtable arrays.
  4892. if ( !pClassToken -> IsSet ( CLASS_ABSTRACT ) )
  4893. {
  4894. fprintf ( fpHDLFile, "\nconst HDLDESC %s::s_apHdlDescs = { ",
  4895. pClassToken -> GetTagValue ( CLASS_NAME ) );
  4896. // Store the Mondo DISPID int he HDLDesc so we can find it for GetTypeInfo
  4897. if ( HasMondoDispInterface ( pClassToken ) )
  4898. {
  4899. CString szDispName;
  4900. // Map to mondo dispinterface as default dispatch interface.
  4901. szDispName = (pClassToken->IsSet(CLASS_COCLASSNAME)) ?
  4902. pClassToken->GetTagValue (CLASS_COCLASSNAME) :
  4903. pClassToken->GetTagValue(CLASS_NAME);
  4904. fprintf ( fpHDLFile, " &DIID_Disp%s,", (LPCSTR)szDispName );
  4905. }
  4906. else
  4907. {
  4908. fprintf ( fpHDLFile, " NULL," );
  4909. }
  4910. if ( bHashTableExists )
  4911. {
  4912. fprintf ( fpHDLFile, "&%s::s_StringTableAggregate, ",
  4913. pClassToken -> GetTagValue ( CLASS_NAME ) );
  4914. }
  4915. else
  4916. {
  4917. fprintf ( fpHDLFile, "NULL, ");
  4918. }
  4919. if ( numVTblPropDescs )
  4920. {
  4921. fprintf ( fpHDLFile, "%s::s_ppropdescsInVtblOrder%s};\n",
  4922. pClassToken->GetTagValue(CLASS_NAME), pClassToken->GetTagValue(CLASS_INTERFACE) );
  4923. }
  4924. else
  4925. {
  4926. fprintf ( fpHDLFile, "NULL};\n" );
  4927. }
  4928. }
  4929. }
  4930. fprintf ( fpLOGFile, "Generating Property Methods...\n" );
  4931. if ( !GeneratePropMethodImplementation() )
  4932. goto Error;
  4933. fprintf ( fpLOGFile, "Generating Cascaded Property Method Implementations...\n" );
  4934. fprintf ( fpHDLFile, "// Cascaded Property get method implementations\n\n" );
  4935. ThisFilesList.Reset();
  4936. while ( pClassToken = ThisFilesList.GetNext( TYPE_CLASS ) )
  4937. {
  4938. GenerateGetAAXImplementations(pClassToken);
  4939. GenerateThunkContextImplemenation(pClassToken);
  4940. }
  4941. fprintf ( fpHDLFile, "\n" );
  4942. fprintf ( fpHDLFile, "#endif _cxx_\n" );
  4943. fprintf ( fpHDLFile, "\n" );
  4944. fprintf ( fpHDLFile, "#undef _cxx_\n" );
  4945. fprintf ( fpHDLFile, "\n" );
  4946. fprintf ( fpLOGFile, "Generating Class Includes...\n" );
  4947. if ( !GenerateClassIncludes() )
  4948. goto Error;
  4949. return TRUE;
  4950. Error:
  4951. return FALSE;
  4952. }
  4953. FILE *OpenMaxlengthFile(LPCSTR pszPDLFileName, LPCSTR pszOutputPath)
  4954. {
  4955. char chMaxLenFileName[255];
  4956. FILE *fpMaxLenFile = NULL;
  4957. BOOL fOpenNew = TRUE;
  4958. strcpy(chMaxLenFileName, pszOutputPath);
  4959. strcat(chMaxLenFileName, FILENAME_SEPARATOR_STR "maxlen.txt");
  4960. fpMaxLenFile = fopen(chMaxLenFileName, "r");
  4961. if (fpMaxLenFile)
  4962. {
  4963. char chMarker[6];
  4964. if (fread(chMarker, sizeof(char), 5, fpMaxLenFile))
  4965. {
  4966. if (!_stricmp(chMarker, "XXXXX"))
  4967. {
  4968. fOpenNew = FALSE;
  4969. }
  4970. }
  4971. fclose(fpMaxLenFile);
  4972. }
  4973. if (fOpenNew)
  4974. {
  4975. fpMaxLenFile = fopen(chMaxLenFileName, "w");
  4976. if (fpMaxLenFile)
  4977. {
  4978. fprintf(fpMaxLenFile, "XXXXX Key Value Glossary:\n");
  4979. fprintf(fpMaxLenFile, "-------------------------------\n");
  4980. fprintf(fpMaxLenFile, "pdlUrlLen = 4096 // url strings\n");
  4981. fprintf(fpMaxLenFile, "pdlToken = 128 // strings that really are some form of a token\n");
  4982. fprintf(fpMaxLenFile, "pdlLength = 128 // strings that really are numeric lengths\n");
  4983. fprintf(fpMaxLenFile, "pdlColor = 128 // strings that really are color values\n");
  4984. fprintf(fpMaxLenFile, "pdlNoLimit = 0xFFFF // strings that have no limit on their max lengths\n");
  4985. fprintf(fpMaxLenFile, "pdlEvent = pdlNoLimit // strings that could be assigned to onfoo event properties\n\n");
  4986. fprintf(fpMaxLenFile, "MAX LENGTH CONSTANTS FOR OM PROPERTIES AND METHODS\n");
  4987. fprintf(fpMaxLenFile, "-----------------------------------------------------------------------------------\n\n");
  4988. }
  4989. }
  4990. else
  4991. {
  4992. fpMaxLenFile = fopen(chMaxLenFileName, "a");
  4993. }
  4994. return fpMaxLenFile;
  4995. }
  4996. int
  4997. CPDLParser::Parse ( char *szInputFile,
  4998. char *szOutputFileRoot,
  4999. char *szPDLFileName,
  5000. char *szOutputPath,
  5001. BOOL fDebugging )
  5002. {
  5003. #if 0
  5004. if (strcmp(szPDLFileName, "iframe.pdl") == 0)
  5005. __asm {int 3};
  5006. #endif
  5007. int nReturnCode = 0;
  5008. char szFileName [ MAX_PATH+1 ];
  5009. char szErrorText [ MAX_LINE_LEN+1 ];
  5010. #ifdef COMPLUS_SHIM
  5011. BOOL fWriteHeader = FALSE;
  5012. #endif
  5013. _pszPDLFileName = szPDLFileName;
  5014. _pszOutputFileRoot = szOutputFileRoot;
  5015. _pszInputFile = szInputFile;
  5016. _pszOutputPath = szOutputPath;
  5017. fpMaxLenFile = OpenMaxlengthFile(szPDLFileName, szOutputPath);
  5018. // Read the input file a line at a time, for each line tokenise and
  5019. // parse
  5020. strcpy ( szFileName, szOutputPath );
  5021. strcat ( szFileName, "LOG" );
  5022. fpLOGFile = fopen ( szFileName, "w" );
  5023. if ( !fpLOGFile )
  5024. {
  5025. printf ( szErrorText, "Can't open log file %s\n", szFileName );
  5026. ReportError ( szErrorText );
  5027. goto error;
  5028. }
  5029. fprintf ( fpLOGFile, "InputBuffer = %s\n", szInputFile );
  5030. fprintf ( fpLOGFile, "OuputFileRoot = %s\n", szOutputFileRoot );
  5031. fprintf ( fpLOGFile, "PDLFileName = %s\n", szPDLFileName );
  5032. fprintf ( fpLOGFile, "LogFileName =% s\n", szFileName );
  5033. // All files open and raring to go....
  5034. if ( !ParseInputFile ( fDebugging ) )
  5035. {
  5036. goto error;
  5037. }
  5038. // Create the HDL File
  5039. strcpy ( szFileName, szOutputFileRoot );
  5040. strcat ( szFileName, ".hdl" );
  5041. fpHDLFile = fopen ( szFileName, "w" );
  5042. if ( !fpHDLFile )
  5043. {
  5044. printf ( szErrorText, "Can't open HDL output file %s\n", szFileName );
  5045. ReportError ( szErrorText );
  5046. goto error;
  5047. }
  5048. #ifdef COMPLUS_SHIM
  5049. // Create the COM+ header file
  5050. strcpy ( szFileName, _pszOutputPath );
  5051. strcat ( szFileName, "\\" );
  5052. strcat ( szFileName, "MSProxy.h" );
  5053. fpHComPlusFile = fopen ( szFileName, "r" );
  5054. if (!fpHComPlusFile)
  5055. {
  5056. fWriteHeader = TRUE;
  5057. }
  5058. else
  5059. {
  5060. fclose(fpHComPlusFile);
  5061. }
  5062. fpHComPlusFile = fopen ( szFileName, "a" );
  5063. if ( !fpHComPlusFile )
  5064. {
  5065. printf ( szErrorText, "Can't open COM+ output file %s\n", szFileName );
  5066. ReportError ( szErrorText );
  5067. goto error;
  5068. }
  5069. // Only write the header first time through not when each PDL is parsed.
  5070. if (fWriteHeader)
  5071. {
  5072. fprintf(fpHComPlusFile, "[managed, com] __interface ICOMCookie\n");
  5073. fprintf(fpHComPlusFile, "{\n");
  5074. fprintf(fpHComPlusFile, "public:\n");
  5075. fprintf(fpHComPlusFile, "\tunsigned int getCOMCookie();\n");
  5076. fprintf(fpHComPlusFile, "};\n\n");
  5077. }
  5078. // Create the COM+ source file
  5079. strcpy ( szFileName, _pszOutputPath );
  5080. strcat ( szFileName, "\\" );
  5081. strcat ( szFileName, "MSProxy.cpp" );
  5082. fpCComPlusFile = fopen ( szFileName, "r" );
  5083. if (!fpCComPlusFile)
  5084. {
  5085. fWriteHeader = TRUE;
  5086. }
  5087. else
  5088. {
  5089. fclose(fpCComPlusFile);
  5090. }
  5091. fpCComPlusFile = fopen ( szFileName, "a" );
  5092. if ( !fpCComPlusFile )
  5093. {
  5094. printf ( szErrorText, "Can't open COM+ output file %s\n", szFileName );
  5095. ReportError ( szErrorText );
  5096. goto error;
  5097. }
  5098. // Only write the header first time through not when each PDL is parsed.
  5099. if (fWriteHeader)
  5100. {
  5101. fprintf(fpCComPlusFile, "#import <MSCorLib.dll>\n\n");
  5102. fprintf(fpCComPlusFile, "// Some types COM+ doesn't know remapped.\n");
  5103. fprintf(fpCComPlusFile, "#define LONG long\n\n");
  5104. fprintf(fpCComPlusFile, "#include \"MSProxy.h\"\n");
  5105. fprintf(fpCComPlusFile, "#include \"TComPlus.hxx\"\n\n\n");
  5106. }
  5107. #endif // COMPLUS_SHIM
  5108. // Create the IDL File
  5109. strcpy ( szFileName, szOutputFileRoot );
  5110. strcat ( szFileName, ".idl" );
  5111. fpIDLFile = fopen ( szFileName, "w" );
  5112. if ( !fpIDLFile )
  5113. {
  5114. printf ( szErrorText, "Can't open IDL output file %s\n", szFileName );
  5115. ReportError ( szErrorText );
  5116. goto error;
  5117. }
  5118. // Create the external Header file for the SDK users
  5119. // Create the HDL File
  5120. strcpy ( szFileName, szOutputFileRoot );
  5121. strcat ( szFileName, ".h" ); // For now
  5122. fpHeaderFile = fopen ( szFileName, "w" );
  5123. if ( !fpHeaderFile )
  5124. {
  5125. printf ( szErrorText, "Can't open Header output file %s\n", szFileName );
  5126. ReportError ( szErrorText );
  5127. goto error;
  5128. }
  5129. // Create the external DISPIDs file for the SDK users
  5130. strcpy ( szFileName, szOutputFileRoot );
  5131. strcat ( szFileName, ".dsp" ); // For now
  5132. fpDISPIDFile = fopen ( szFileName, "w" );
  5133. if ( !fpDISPIDFile )
  5134. {
  5135. printf ( szErrorText, "Can't open DISPID output file %s\n", szFileName );
  5136. ReportError ( szErrorText );
  5137. goto error;
  5138. }
  5139. // Create function signatures required for the custom OLEAutomation invoke.
  5140. if ( !LoadSignatures (szOutputPath) )
  5141. {
  5142. ReportError ( "Signature file missing" );
  5143. goto error;
  5144. }
  5145. #if COLLECT_STATISTICS==1
  5146. LoadStatistics (szOutputPath);
  5147. #endif
  5148. // Parsed Successfully - generate HDL file
  5149. if ( !GenerateHDLFile () )
  5150. {
  5151. printf ( szErrorText, "Can't create HDL output file %s%s.hdl\n",
  5152. szOutputFileRoot, szFileName );
  5153. ReportError ( szErrorText );
  5154. goto error;
  5155. }
  5156. strcpy ( szFileName, szOutputFileRoot );
  5157. strcat ( szFileName, ".idl" ); // For now hxx
  5158. if ( !GenerateIDLFile( szFileName ) )
  5159. {
  5160. printf ( szErrorText, "Can't create IDL file %s\n", szFileName );
  5161. ReportError ( szErrorText );
  5162. goto error;
  5163. }
  5164. // Generate the .H file with just enums & interface decls in
  5165. GenerateHeaderFile();
  5166. // Generate the external DISPID's file
  5167. GenerateExternalInterfaceDISPIDs();
  5168. GenerateEventDISPIDs ( fpDISPIDFile, FALSE );
  5169. // Create/Open the HTML index file
  5170. strcpy ( szFileName, szOutputPath );
  5171. strcat ( szFileName, FILENAME_SEPARATOR_STR "AllIndex.htm" );
  5172. fpHTMIndexFile = fopen ( szFileName, "a+" );
  5173. /* rgardner - commented out for now - not very up-to-date or useful any more
  5174. // Create the HTM File
  5175. strcpy ( szFileName, szOutputFileRoot );
  5176. strcat ( szFileName, ".htm" );
  5177. fpHTMFile = fopen ( szFileName, "w" );
  5178. if ( !GenerateHTMFile( ) )
  5179. {
  5180. printf ( szErrorText, "Can't create HTM file %s\n", szFileName );
  5181. ReportError ( szErrorText );
  5182. goto error;
  5183. }
  5184. */
  5185. // Update the signature file is any changes.
  5186. if (!SaveSignatures( szOutputPath ))
  5187. {
  5188. ReportError ( "Signature file save problem." );
  5189. goto error;
  5190. }
  5191. #if COLLECT_STATISTICS==1
  5192. SaveStatistics (szOutputPath);
  5193. #endif
  5194. goto cleanup;
  5195. error:
  5196. if ( nReturnCode == 0 )
  5197. nReturnCode = 1;
  5198. cleanup:
  5199. return nReturnCode;
  5200. }
  5201. #if COLLECT_STATISTICS==1
  5202. void CPDLParser::LoadStatistics ( char *pszOutputPath )
  5203. {
  5204. BOOL bRetVal;
  5205. char *buffer = NULL;
  5206. CString szFileName;
  5207. FILE *fpStatFile = NULL;
  5208. szFileName = pszOutputPath;
  5209. szFileName += FILENAME_SEPARATOR_STR "stats.dat";
  5210. fpStatFile = fopen ( szFileName, "r" );
  5211. if ( !fpStatFile )
  5212. {
  5213. char chInitFuncSig[2] = { '\0', '\0' };
  5214. fpStatFile = fopen ( szFileName, "w+");
  5215. if ( !fpStatFile )
  5216. {
  5217. ReportError ( "Can't create statistics file" );
  5218. goto error;
  5219. }
  5220. fwrite ( chInitFuncSig, 1, sizeof(chInitFuncSig), fpStatFile );
  5221. }
  5222. if ( fseek( fpStatFile, 0, SEEK_END ) == 0 )
  5223. {
  5224. fpos_t pos;
  5225. if ( fgetpos( fpStatFile, &pos ) == 0 )
  5226. {
  5227. int i = 0;
  5228. int cLines;
  5229. buffer = new char[pos];
  5230. if (buffer == NULL)
  5231. goto error;
  5232. fseek( fpStatFile, 0, SEEK_SET );
  5233. if ( fread ( buffer, 1, pos, fpStatFile ) != pos )
  5234. goto error;
  5235. // Intialize to 0.
  5236. for (i = 0; i < MAX_STATS; i++)
  5237. rgcStats[i] = 0;
  5238. // Populate the statics array.
  5239. i = 0;
  5240. cLines = 0;
  5241. while ( buffer[i] || buffer[i + 1] )
  5242. {
  5243. int cStr = strlen(buffer + i);
  5244. rgcStats[cLines] = atol(buffer + i);
  5245. cLines ++;
  5246. i += cStr + 1;
  5247. }
  5248. }
  5249. }
  5250. bRetVal = TRUE;
  5251. cleanup:
  5252. delete buffer;
  5253. fclose ( fpStatFile );
  5254. return;
  5255. error:
  5256. bRetVal = FALSE;
  5257. goto cleanup;
  5258. }
  5259. void CPDLParser::SaveStatistics ( char *pszOutputPath )
  5260. {
  5261. //DebugBreak();
  5262. BOOL bRetVal = TRUE;
  5263. if (rgcStats)
  5264. {
  5265. int i;
  5266. CString szFileName;
  5267. FILE *fpStatFile = NULL;
  5268. char buffer[32];
  5269. szFileName = pszOutputPath;
  5270. szFileName += FILENAME_SEPARATOR_STR "stats.dat";
  5271. fpStatFile = fopen ( szFileName, "w" );
  5272. // Write array to file.
  5273. if ( fseek( fpStatFile, 0, SEEK_SET ) != 0 )
  5274. return;
  5275. i = 0;
  5276. while (i < MAX_STATS)
  5277. {
  5278. sprintf( buffer, "%i", rgcStats[i] );
  5279. fwrite ( buffer, 1, strlen(buffer) + 1, fpStatFile );
  5280. i++;
  5281. }
  5282. // Double NULL at the end.
  5283. buffer[0] = '\0';
  5284. buffer[1] = '\0';
  5285. fwrite ( &buffer, 1, 2, fpStatFile );
  5286. fclose(fpStatFile);
  5287. }
  5288. return;
  5289. }
  5290. #endif
  5291. void CPDLParser::RemoveSignatures()
  5292. {
  5293. if (rgszSignatures)
  5294. {
  5295. int i = cSignatures;
  5296. while (i--)
  5297. delete [] rgszSignatures[i];
  5298. delete [] rgszSignatures;
  5299. rgszSignatures = NULL;
  5300. }
  5301. if (rgszIIDs)
  5302. {
  5303. int i = cIIDs;
  5304. while (i--)
  5305. delete [] rgszIIDs[i];
  5306. delete [] rgszIIDs;
  5307. rgszIIDs = NULL;
  5308. }
  5309. }
  5310. BOOL CPDLParser::LoadSignatures ( char *pszOutputPath )
  5311. {
  5312. BOOL bRetVal;
  5313. char *buffer = NULL;
  5314. CString szFileName;
  5315. FILE *fpSigFile = NULL;
  5316. rgszSignatures = NULL;
  5317. cOnFileSignatures = 0;
  5318. cOnFileIIDs = 0;
  5319. cSignatures = 0;
  5320. cIIDs = 0;
  5321. szFileName = pszOutputPath;
  5322. szFileName += FILENAME_SEPARATOR_STR "funcsig.dat";
  5323. /*
  5324. if (strcmp(_pszPDLFileName, "select.pdl") == 0 || strcmp(_pszPDLFileName, "header.pdl") == 0)
  5325. __asm { int 3 };
  5326. */
  5327. fpSigFile = fopen ( szFileName, "rb" );
  5328. if ( !fpSigFile )
  5329. {
  5330. char chInitFuncSig[6] = { '\0', '\0', '\0', '\0', '\0', '\0' };
  5331. fpSigFile = fopen ( szFileName, "w+");
  5332. if ( !fpSigFile )
  5333. {
  5334. ReportError ( "Can't create function signature file" );
  5335. goto error;
  5336. }
  5337. fwrite ( chInitFuncSig, 1, sizeof(chInitFuncSig), fpSigFile );
  5338. }
  5339. if ( fseek( fpSigFile, 0, SEEK_END ) == 0 )
  5340. {
  5341. fpos_t pos;
  5342. if ( fgetpos( fpSigFile, &pos ) == 0 )
  5343. {
  5344. int i = 0;
  5345. int cLines;
  5346. buffer = new char[pos];
  5347. if (buffer == NULL)
  5348. goto error;
  5349. fseek( fpSigFile, 0, SEEK_SET );
  5350. fread ( buffer, 1, pos, fpSigFile );
  5351. // Number of entries for each signatures and IIDs
  5352. cOnFileSignatures = buffer[0] & 0x000000ff; // First byte is # signature
  5353. cOnFileIIDs = buffer[1] & 0x000000ff; // 2nd byte is # IIDs
  5354. // Pre-allocate the signature array.
  5355. rgszSignatures = new char *[cOnFileSignatures + 1];
  5356. if ( !rgszSignatures )
  5357. goto error;
  5358. // Pre-allocate the IIDs array.
  5359. rgszIIDs = new char *[cOnFileIIDs + 1];
  5360. if ( !rgszIIDs )
  5361. goto error;
  5362. // Intialize to NULL for error handling.
  5363. for (i = 0; i <= cOnFileSignatures; i++)
  5364. rgszSignatures[i] = NULL;
  5365. cSignatures = cOnFileSignatures;
  5366. for (i = 0; i <= cOnFileIIDs; i++)
  5367. rgszIIDs[i] = NULL;
  5368. cIIDs = cOnFileIIDs;
  5369. // Populate the signature array.
  5370. i = 4;
  5371. cLines = 0;
  5372. while ( cLines != cSignatures )
  5373. {
  5374. int cStr = strlen(buffer + i);
  5375. rgszSignatures[cLines] = new char[cStr + 1];
  5376. if (!rgszSignatures[cLines])
  5377. goto error;
  5378. strcpy(rgszSignatures[cLines], buffer + i);
  5379. cLines ++;
  5380. i += cStr + 1;
  5381. }
  5382. // Populate the IIDs array.
  5383. cLines = 0;
  5384. while ( cLines != cIIDs )
  5385. {
  5386. int cStr = strlen(buffer + i);
  5387. rgszIIDs[cLines] = new char[cStr + 1];
  5388. if (!rgszIIDs[cLines])
  5389. goto error;
  5390. strcpy(rgszIIDs[cLines], buffer + i);
  5391. cLines ++;
  5392. i += cStr + 1;
  5393. }
  5394. }
  5395. }
  5396. bRetVal = TRUE;
  5397. cleanup:
  5398. fclose ( fpSigFile );
  5399. return bRetVal;
  5400. error:
  5401. delete [] buffer;
  5402. RemoveSignatures();
  5403. bRetVal = FALSE;
  5404. goto cleanup;
  5405. }
  5406. BOOL CPDLParser::SaveSignatures ( char *pszOutputPath )
  5407. {
  5408. if (rgszSignatures || rgszIIDs)
  5409. {
  5410. if (cOnFileSignatures != cSignatures || cOnFileIIDs != cIIDs)
  5411. {
  5412. int i;
  5413. CString szFileName;
  5414. FILE *fpSigFile = NULL;
  5415. char cHeaderFuncSig[4] = { '\0', '\0', '\0', '\0' };
  5416. szFileName = pszOutputPath;
  5417. szFileName += FILENAME_SEPARATOR_STR "funcsig.dat";
  5418. fpSigFile = fopen ( szFileName, "wb" );
  5419. // Write array to file.
  5420. if ( fseek( fpSigFile, 0, SEEK_SET ) != 0 )
  5421. return FALSE;
  5422. // Write out the header on count of each type.
  5423. cHeaderFuncSig[0] = (char)cSignatures;
  5424. cHeaderFuncSig[1] = (char)cIIDs;
  5425. fwrite ( cHeaderFuncSig, 1, sizeof(cHeaderFuncSig), fpSigFile );
  5426. i = 0;
  5427. while (i < cSignatures)
  5428. {
  5429. if ( rgszSignatures[i] )
  5430. {
  5431. fwrite ( rgszSignatures[i], 1, strlen(rgszSignatures[i]) + 1, fpSigFile );
  5432. }
  5433. i++;
  5434. }
  5435. i = 0;
  5436. while (i < cIIDs)
  5437. {
  5438. if ( rgszIIDs[i] )
  5439. {
  5440. fwrite ( rgszIIDs[i], 1, strlen(rgszIIDs[i]) + 1, fpSigFile );
  5441. }
  5442. i++;
  5443. }
  5444. // Write out extra zero to mark end of file.
  5445. cHeaderFuncSig[0] = '\0';
  5446. fwrite ( cHeaderFuncSig, 1, 1, fpSigFile );
  5447. fclose(fpSigFile);
  5448. }
  5449. // Dispose of signature array (IIDs is disposed of too).
  5450. RemoveSignatures();
  5451. }
  5452. return TRUE;
  5453. }
  5454. void
  5455. CPDLParser::MakeSignature (LPCSTR szType, LPCSTR szSignature, CString & szLookup)
  5456. {
  5457. char *szWork;
  5458. // Any empty string for type or signature is an error.
  5459. if (!szType[0] || !szSignature[0])
  5460. {
  5461. return;
  5462. }
  5463. // Replace all * with p (e.g., BSTR * is BSTRP and long * is longP).
  5464. while ((szWork = strchr(szSignature, '*')) != NULL)
  5465. *szWork = 'p';
  5466. // Replace all ( with P.
  5467. while ((szWork = strchr(szSignature, '(')) != NULL)
  5468. *szWork = 'P';
  5469. // Replace all ) with P.
  5470. while ((szWork = strchr(szSignature, ')')) != NULL)
  5471. *szWork = 'P';
  5472. szLookup = szType;
  5473. szLookup += "_";
  5474. szLookup += szSignature;
  5475. }
  5476. BOOL CPDLParser::FindAndAddSignature ( LPCSTR szType, LPCSTR szSignature, LPSTR pszInvokeMethod )
  5477. {
  5478. BOOL bRetVal = NULL;
  5479. CString szLookup;
  5480. char **rgNewArray = NULL;
  5481. if (pszInvokeMethod && rgszSignatures)
  5482. {
  5483. strcpy( pszInvokeMethod, "ERROR in PDLParse: No custom invoke method");
  5484. MakeSignature(szType, szSignature, szLookup);
  5485. // Look for the signature
  5486. for (int i = 0; i < cSignatures; i++)
  5487. {
  5488. if ( strcmp ( rgszSignatures[i], szLookup ) == 0 )
  5489. {
  5490. goto success;
  5491. }
  5492. }
  5493. // If not found then add this signature.
  5494. cSignatures++;
  5495. rgNewArray = new char *[cSignatures + 1]; // Take into account the NULL at end.
  5496. if (!rgNewArray)
  5497. goto cleanup;
  5498. memcpy(rgNewArray, rgszSignatures, sizeof(char *) * cSignatures);
  5499. rgNewArray[cSignatures - 1] = new char[szLookup.Length() + 1];
  5500. strcpy(rgNewArray[cSignatures - 1], szLookup);
  5501. rgNewArray[cSignatures] = NULL;
  5502. delete rgszSignatures;
  5503. rgszSignatures = rgNewArray;
  5504. success:
  5505. strcpy(pszInvokeMethod, "IDX_");
  5506. strcat(pszInvokeMethod, (LPCSTR)szLookup);
  5507. bRetVal = TRUE;
  5508. }
  5509. cleanup:
  5510. return bRetVal;
  5511. }
  5512. int CPDLParser::FindAndAddIIDs ( CString szInterface )
  5513. {
  5514. char **rgNewArray = NULL;
  5515. // Any empty string interface name is an error.
  5516. if (szInterface.Length() == 0)
  5517. return -1; // Error.
  5518. // Look for the signature
  5519. for (int i = 0; i < cIIDs; i++)
  5520. {
  5521. if ( strcmp ( rgszIIDs[i], (LPCSTR)szInterface ) == 0 )
  5522. {
  5523. goto success;
  5524. }
  5525. }
  5526. // If not found then add this IID.
  5527. cIIDs++;
  5528. rgNewArray = new char *[cIIDs + 1]; // Take into account the NULL at end.
  5529. if (!rgNewArray)
  5530. return -1;
  5531. memcpy(rgNewArray, rgszIIDs, sizeof(char *) * cIIDs);
  5532. rgNewArray[cIIDs - 1] = new char[szInterface.Length() + 1];
  5533. strcpy(rgNewArray[cIIDs - 1], (LPCSTR)szInterface);
  5534. rgNewArray[cIIDs] = NULL;
  5535. delete rgszIIDs;
  5536. rgszIIDs = rgNewArray;
  5537. success:
  5538. return i;
  5539. }
  5540. BOOL CPDLParser::GenerateIDLFile ( char *szFileName )
  5541. {
  5542. CTokenListWalker ThisFileList ( pRuntimeList, _pszPDLFileName );
  5543. Token * pInterfaceToken;
  5544. Token * pClassToken;
  5545. Token * pEnumToken;
  5546. Token * pStructToken;
  5547. ThisFileList.Reset();
  5548. while ( pInterfaceToken = ThisFileList.GetNext ( TYPE_EVENT ) )
  5549. {
  5550. if ( !pInterfaceToken -> IsSet ( EVENT_ABSTRACT ) &&
  5551. pInterfaceToken -> IsSet ( EVENT_GUID ) )
  5552. {
  5553. GenerateIDLInterfaceDecl ( pInterfaceToken,
  5554. pInterfaceToken -> GetTagValue ( EVENT_GUID ),
  5555. pInterfaceToken -> GetTagValue ( EVENT_SUPER ) );
  5556. }
  5557. }
  5558. ThisFileList.Reset();
  5559. while (pEnumToken = ThisFileList.GetNext(TYPE_ENUM))
  5560. {
  5561. GenerateIncludeEnum(pEnumToken, FALSE, fpIDLFile);
  5562. }
  5563. //
  5564. // Generate all the structs
  5565. //
  5566. ThisFileList.Reset();
  5567. while (pStructToken = ThisFileList.GetNext(TYPE_STRUCT))
  5568. {
  5569. GenerateStruct(pStructToken, fpIDLFile);
  5570. }
  5571. ThisFileList.Reset();
  5572. while ( pInterfaceToken = ThisFileList.GetNext ( TYPE_INTERFACE ) )
  5573. {
  5574. if ( !pInterfaceToken -> IsSet ( INTERFACE_ABSTRACT ) &&
  5575. pInterfaceToken -> IsSet ( INTERFACE_GUID ) )
  5576. {
  5577. GenerateIDLInterfaceDecl ( pInterfaceToken,
  5578. pInterfaceToken -> GetTagValue ( INTERFACE_GUID ),
  5579. pInterfaceToken -> GetTagValue ( INTERFACE_SUPER ) );
  5580. }
  5581. else if ( !pInterfaceToken -> IsSet ( INTERFACE_ABSTRACT ) &&
  5582. !pInterfaceToken -> IsSet ( INTERFACE_GUID ) )
  5583. {
  5584. // Generate a forward declare
  5585. CString szInterfaceName;
  5586. szInterfaceName = pInterfaceToken -> GetTagValue ( INTERFACE_NAME );
  5587. if ( szInterfaceName != "IDispatch" &&
  5588. szInterfaceName != "IUnknown" )
  5589. {
  5590. fprintf ( fpIDLFile, "interface %s;\n",
  5591. pInterfaceToken -> GetTagValue ( NAME_TAG ) );
  5592. }
  5593. }
  5594. }
  5595. ThisFileList.Reset();
  5596. while (pClassToken = ThisFileList.GetNext(TYPE_CLASS))
  5597. {
  5598. CTokenListWalker ChildWalker(pClassToken);
  5599. Token *pChildToken;
  5600. int cImplements = 0;
  5601. // Find out how many implements are in the class.
  5602. while (pChildToken = ChildWalker.GetNext())
  5603. {
  5604. if (pChildToken->GetType() == TYPE_IMPLEMENTS)
  5605. {
  5606. cImplements++;
  5607. }
  5608. }
  5609. // Any class with more than one implements needs a mondodispid to be specified.
  5610. if (pClassToken->IsSet(CLASS_GUID) && cImplements && !pClassToken->IsSet(CLASS_MONDOGUID))
  5611. {
  5612. char szErrorText [ MAX_LINE_LEN+1 ];
  5613. sprintf(szErrorText,
  5614. "class: %s needs a mondoguid when implements are specified for a coclass.\n",
  5615. pClassToken->GetTagValue(CLASS_NAME));
  5616. ReportError(szErrorText);
  5617. return FALSE;
  5618. }
  5619. // Generate non-dual dispinterface? This is determined by the mondoguid
  5620. // keyword being used int the class. If this guid is specified then
  5621. // we'll generate the mondodisp interface is use it as the default
  5622. // dispatch interface for the coclass.
  5623. if (pClassToken->IsSet(CLASS_MONDOGUID))
  5624. {
  5625. LPSTR pMondoGUID;
  5626. CString szInterface;
  5627. szInterface = pClassToken->GetTagValue(CLASS_INTERFACE);
  5628. pInterfaceToken = FindInterface(szInterface);
  5629. pMondoGUID = pClassToken->GetTagValue(CLASS_MONDOGUID);
  5630. // If we have a GUID then the dispinterface GUID must be in the
  5631. // range 0x3050f500 to 0x3050f5a0
  5632. if (pMondoGUID[0] != '3' ||
  5633. pMondoGUID[1] != '0' ||
  5634. pMondoGUID[2] != '5' ||
  5635. pMondoGUID[3] != '0' ||
  5636. pMondoGUID[4] != 'f' ||
  5637. pMondoGUID[5] != '5' ||
  5638. !((pMondoGUID[6] >= '0' &&
  5639. pMondoGUID[6] <= '9') ||
  5640. pMondoGUID[6] == 'a') ||
  5641. !((pMondoGUID[7] >= '0' &&
  5642. pMondoGUID[7] <= '9') ||
  5643. (pMondoGUID[7] >= 'a' &&
  5644. pMondoGUID[7] <= 'f')))
  5645. {
  5646. char szErrorText [ MAX_LINE_LEN+1 ];
  5647. sprintf(szErrorText,
  5648. "The mondoguid must be in the range 0x3050f500 to 0x3050f5a0 for class: %s\n",
  5649. pClassToken->GetTagValue(CLASS_NAME));
  5650. ReportError(szErrorText);
  5651. return FALSE;
  5652. }
  5653. // Generate the default dispinterface
  5654. GenerateIDLInterfaceDecl(pInterfaceToken,
  5655. pMondoGUID,
  5656. pInterfaceToken->GetTagValue(INTERFACE_SUPER),
  5657. TRUE,
  5658. pClassToken);
  5659. }
  5660. if ( pClassToken-> IsSet(CLASS_GUID) &&
  5661. pClassToken->IsSet(CLASS_INTERFACE))
  5662. {
  5663. GenerateCoClassDecl(pClassToken);
  5664. }
  5665. }
  5666. return TRUE;
  5667. }
  5668. void CPDLParser::GenerateIDLInterfaceDecl (Token *pInterfaceToken,
  5669. char *pszGUID,
  5670. char *pszSuper,
  5671. BOOL fDispInterface/*= FALSE*/,
  5672. Token *pClassToken/*= NULL*/)
  5673. {
  5674. BOOL fImplements = FALSE;
  5675. if ( pInterfaceToken -> GetType() == TYPE_EVENT )
  5676. {
  5677. fprintf ( fpIDLFile, "[\n hidden,\n" );
  5678. fprintf ( fpIDLFile, " uuid(%s)\n]\ndispinterface %s\n{",
  5679. pszGUID, pInterfaceToken -> GetTagValue ( NAME_TAG ) );
  5680. fprintf ( fpIDLFile, "\nproperties:\nmethods:\n" );
  5681. }
  5682. else
  5683. {
  5684. if (fDispInterface)
  5685. {
  5686. fprintf ( fpIDLFile, "[\n hidden,\n" );
  5687. fprintf ( fpIDLFile, " uuid(%s)\n]\ndispinterface Disp%s\n{\nproperties:\nmethods:\n",
  5688. pszGUID,
  5689. pClassToken->IsSet(CLASS_COCLASSNAME) ?
  5690. pClassToken->GetTagValue(CLASS_COCLASSNAME) :
  5691. pClassToken->GetTagValue(CLASS_NAME));
  5692. }
  5693. else
  5694. {
  5695. if (!PrimaryTearoff(pInterfaceToken) && (!pszSuper || !*pszSuper))
  5696. ReportError ( "Interfaces w/o tearoff need super:IDispatch\n" );
  5697. if (pInterfaceToken->IsSet(INTERFACE_CUSTOM) &&
  5698. pszSuper &&
  5699. *pszSuper)
  5700. {
  5701. fprintf(fpIDLFile, "[\n object,\n pointer_default(unique),\n" );
  5702. fprintf ( fpIDLFile, " uuid(%s)\n]\ninterface %s : %s\n{\n",
  5703. pszGUID,
  5704. pInterfaceToken -> GetTagValue ( NAME_TAG ),
  5705. pszSuper);
  5706. }
  5707. else
  5708. {
  5709. fprintf ( fpIDLFile, "[\n odl,\n oleautomation,\n dual,\n" );
  5710. fprintf ( fpIDLFile, " uuid(%s)\n]\ninterface %s : %s\n{\n",
  5711. pszGUID,
  5712. pInterfaceToken -> GetTagValue ( NAME_TAG ),
  5713. (PrimaryTearoff(pInterfaceToken) && _stricmp(pszSuper, "IHTMLDocument")) ? "IDispatch" : pszSuper);
  5714. }
  5715. }
  5716. }
  5717. // Any implements in the class if so then we want the order of the mongo dispinterface to be decided
  5718. // by the order of the implements and not the super chain.
  5719. if (fDispInterface)
  5720. {
  5721. CTokenListWalker ChildWalker(pClassToken);
  5722. Token *pChildToken;
  5723. while (pChildToken = ChildWalker.GetNext())
  5724. {
  5725. fImplements = pChildToken->GetType() == TYPE_IMPLEMENTS;
  5726. if (fImplements)
  5727. break;
  5728. }
  5729. }
  5730. // Use the super chain for mongo dispinterface?
  5731. if (!fImplements)
  5732. // Yes.
  5733. GenerateMkTypelibDecl(pInterfaceToken, fDispInterface, pClassToken);
  5734. // Any other interfaces exposed in the coclass which are not part of the
  5735. // primary interface chain? Look for implements keyword.
  5736. if (fDispInterface)
  5737. {
  5738. CTokenListWalker ChildWalker(pClassToken);
  5739. Token *pChildToken;
  5740. CString szInterface;
  5741. Token *pInterfToken;
  5742. while (pChildToken = ChildWalker.GetNext())
  5743. {
  5744. if (pChildToken->GetType() == TYPE_IMPLEMENTS)
  5745. {
  5746. szInterface = pChildToken->GetTagValue(IMPLEMENTS_NAME);
  5747. pInterfToken = FindInterface(szInterface);
  5748. if (pInterfToken)
  5749. {
  5750. GenerateMkTypelibDecl(pInterfToken, fDispInterface, pClassToken);
  5751. }
  5752. }
  5753. }
  5754. }
  5755. fprintf(fpIDLFile, "};\n");
  5756. }
  5757. void CPDLParser::ComputePropType ( Token *pPropertyToken,
  5758. CString &szProp, BOOL fComment )
  5759. {
  5760. char szText [ MAX_LINE_LEN+1 ];
  5761. szProp = "";
  5762. // Through the index/indextype & index1/indextype1 pdl tags
  5763. // you can provide up to two additional args for the property definition
  5764. sprintf ( szText, fComment ? "/* [in] */ %s %s" : "[in] %s %s",
  5765. pPropertyToken -> GetTagValue ( PROPERTY_INDEXTYPE ),
  5766. pPropertyToken -> GetTagValue ( PROPERTY_INDEX ) );
  5767. pPropertyToken -> AddParam ( szProp, PROPERTY_INDEX, szText );
  5768. sprintf ( szText, fComment ? "/* [in] */ %s %s" : "[in] %s %s",
  5769. pPropertyToken -> GetTagValue ( PROPERTY_INDEXTYPE1 ),
  5770. pPropertyToken -> GetTagValue ( PROPERTY_INDEX1 ));
  5771. pPropertyToken -> AddParam ( szProp, PROPERTY_INDEX1, szText );
  5772. if ( szProp [ 0 ] != '\0' )
  5773. szProp += ",";
  5774. }
  5775. void CPDLParser::GenerateMkTypelibDecl ( Token *pInterfaceToken, BOOL fDispInterface/* = FALSE*/, Token *pClass /* =NULL */)
  5776. {
  5777. Token *pChildToken;
  5778. Token *pArgToken;
  5779. CString szArg;
  5780. CString szProp;
  5781. CString szAutomationType;
  5782. BOOL fFirst;
  5783. CString szInterfaceName,szMethodName,szPropertyName;
  5784. CTokenListWalker ChildWalker ( pInterfaceToken );
  5785. if ( pInterfaceToken -> GetType() == TYPE_EVENT &&
  5786. pInterfaceToken -> IsSet ( EVENT_SUPER ) )
  5787. {
  5788. CTokenListWalker WholeList(pRuntimeList);
  5789. Token *pSuperEvent = WholeList.GetNext ( TYPE_EVENT,
  5790. pInterfaceToken -> GetTagValue ( EVENT_SUPER ) );
  5791. if ( pSuperEvent )
  5792. GenerateMkTypelibDecl ( pSuperEvent );
  5793. }
  5794. // Special non-dual dispinterface for the default when the primary interface
  5795. // is a tearoff.
  5796. if (fDispInterface)
  5797. {
  5798. Token *pSuperIntf;
  5799. CString szInterface;
  5800. szInterface = pInterfaceToken->GetTagValue(INTERFACE_SUPER);
  5801. pSuperIntf = FindInterface(szInterface);
  5802. if (pSuperIntf)
  5803. GenerateMkTypelibDecl(pSuperIntf, fDispInterface, pClass);
  5804. }
  5805. szInterfaceName = pInterfaceToken->GetTagValue ( INTERFACE_NAME );
  5806. szInterfaceName.ToUpper();
  5807. while ( pChildToken = ChildWalker.GetNext() )
  5808. {
  5809. if ( pChildToken -> GetType() == TYPE_METHOD )
  5810. {
  5811. // if nopropdesc is set, then this method doesn't
  5812. // participate in the typelib/mondo interface. this happens
  5813. // when the method exists in a base class/interface as well.
  5814. if ( pChildToken->IsSet(METHOD_NOPROPDESC) && fDispInterface)
  5815. continue;
  5816. // Does the property name exist in another interface then the primary
  5817. // interface had better have the override. Otherwise, it's an error
  5818. // MIDL will not allow overloading names.
  5819. if (fDispInterface && pClass)
  5820. {
  5821. CString szPrimaryInterface;
  5822. Token *pPriInterf;
  5823. Token *pExclusiveMember;
  5824. szPrimaryInterface = pClass->GetTagValue(CLASS_INTERFACE);
  5825. pPriInterf = FindInterface(szPrimaryInterface);
  5826. // If working on non-primary interface make sure the method isn't overloaded on
  5827. // the primary, if so it better be marked exclusive.
  5828. if (_strcmpi(szInterfaceName, szPrimaryInterface))
  5829. {
  5830. pExclusiveMember = FindMethodInInterfaceWOPropDesc(pPriInterf, pChildToken, TRUE);
  5831. if (pExclusiveMember)
  5832. {
  5833. char szErrorText [ MAX_LINE_LEN+1 ];
  5834. if (pExclusiveMember->IsSet(METHOD_EXCLUSIVETOSCRIPT))
  5835. continue;
  5836. // Overloaded method -- illegal.
  5837. sprintf(szErrorText, "method %s:%s is overloaded - illegal.\n",
  5838. (LPCSTR)pClass->GetTagValue(CLASS_NAME),
  5839. (LPCSTR)pExclusiveMember->GetTagValue(METHOD_NAME));
  5840. ReportError(szErrorText);
  5841. return;
  5842. }
  5843. }
  5844. }
  5845. if ( pChildToken -> IsSet ( METHOD_VARARG) )
  5846. {
  5847. fprintf ( fpIDLFile, " [vararg");
  5848. }
  5849. else
  5850. {
  5851. fprintf ( fpIDLFile, " [");
  5852. }
  5853. szMethodName = pChildToken -> GetTagValue ( METHOD_NAME );
  5854. if (pChildToken->IsSet(METHOD_NOPROPDESC))
  5855. {
  5856. if (pChildToken->IsSet(METHOD_SZINTERFACEEXPOSE))
  5857. szMethodName = pChildToken->GetTagValue(METHOD_SZINTERFACEEXPOSE);
  5858. }
  5859. szMethodName.ToUpper();
  5860. if ( pChildToken -> IsSet ( METHOD_DISPID ) )
  5861. {
  5862. fprintf ( fpIDLFile, "%sid(DISPID_%s_%s)",
  5863. pChildToken -> IsSet ( METHOD_VARARG ) ? "," : "",
  5864. (LPCSTR)szInterfaceName, (LPCSTR)szMethodName );
  5865. }
  5866. CTokenListWalker ArgListWalker ( pChildToken );
  5867. if (pChildToken->IsSet(METHOD_NOPROPDESC) &&
  5868. pChildToken->IsSet(METHOD_SZINTERFACEEXPOSE))
  5869. {
  5870. szMethodName = pChildToken->GetTagValue(METHOD_SZINTERFACEEXPOSE);
  5871. }
  5872. else
  5873. {
  5874. szMethodName = pChildToken->GetTagValue(METHOD_NAME);
  5875. }
  5876. if (fDispInterface)
  5877. {
  5878. szAutomationType = "void";
  5879. while ( pArgToken = ArgListWalker.GetNext() )
  5880. {
  5881. if (pArgToken->IsSet(METHODARG_RETURNVALUE))
  5882. {
  5883. szAutomationType = pArgToken->IsSet(METHODARG_ATYPE ) ?
  5884. pArgToken->GetTagValue(METHODARG_ATYPE) :
  5885. pArgToken->GetTagValue(METHODARG_TYPE);
  5886. }
  5887. // If the last character is a pointer then the pointer
  5888. // should be removed because that is for dual C++ style
  5889. // interface. DispInterface doesn't need the retval
  5890. // specified as a parameter hence the need for
  5891. // HRESULT funcName(BOOL*) instead of BOOL funcName ().
  5892. int iSzLength = szAutomationType.Length();
  5893. if (iSzLength && szAutomationType[iSzLength - 1] == '*')
  5894. {
  5895. char szTypeNoPtr[MAX_LINE_LEN+1];
  5896. strncpy(szTypeNoPtr, szAutomationType, iSzLength - 1);
  5897. szTypeNoPtr[iSzLength - 1] = '\0';
  5898. szAutomationType = szTypeNoPtr;
  5899. }
  5900. }
  5901. fprintf ( fpIDLFile, "] %s %s(",
  5902. (LPCSTR)szAutomationType,
  5903. (LPCSTR)szMethodName );
  5904. ArgListWalker.Reset();
  5905. }
  5906. else
  5907. {
  5908. fprintf ( fpIDLFile, "] %s %s(",
  5909. pChildToken -> GetTagValue ( METHOD_RETURNTYPE ),
  5910. (LPCSTR)szMethodName );
  5911. }
  5912. fFirst = TRUE;
  5913. while ( pArgToken = ArgListWalker.GetNext() )
  5914. {
  5915. if (!(fDispInterface && pArgToken->IsSet(METHODARG_RETURNVALUE)))
  5916. {
  5917. szArg = "";
  5918. if ( !fFirst )
  5919. fprintf ( fpIDLFile, "," );
  5920. #ifndef WIN16_PARSER
  5921. pArgToken -> AddParamStr ( szArg, METHODARG_DEFAULTVALUE, "defaultvalue(%s)" );
  5922. #endif
  5923. pArgToken -> AddParam ( szArg, METHODARG_OPTIONAL, "optional" );
  5924. pArgToken -> AddParam ( szArg, METHODARG_RETURNVALUE, "retval" );
  5925. pArgToken -> AddParam ( szArg, METHODARG_IN, "in" );
  5926. pArgToken -> AddParam ( szArg, METHODARG_OUT, "out" );
  5927. fprintf ( fpIDLFile, "[%s] %s %s",
  5928. (LPCSTR)szArg,
  5929. // Fixing a bug in the old code
  5930. // Should really get the atype - allow the type if atype not set
  5931. pArgToken -> IsSet ( METHODARG_ATYPE ) ?
  5932. pArgToken -> GetTagValue ( METHODARG_ATYPE ) :
  5933. pArgToken -> GetTagValue ( METHODARG_TYPE ),
  5934. pArgToken -> GetTagValue ( METHODARG_ARGNAME ) );
  5935. fFirst = FALSE;
  5936. }
  5937. }
  5938. fprintf ( fpIDLFile, ");\n" );
  5939. }
  5940. else // Property
  5941. {
  5942. ComputePropType ( pChildToken, szProp, FALSE );
  5943. szAutomationType = pChildToken -> GetTagValue ( PROPERTY_ATYPE );
  5944. // if nopropdesc is set, then this property doesn't
  5945. // participate in the typelib/mondo interface. this happens
  5946. // when the property exists in a base class/interface as well.
  5947. if (pChildToken->IsSet(PROPERTY_NOPROPDESC) && fDispInterface)
  5948. continue;
  5949. // Does the property name exist in another interface then the primary
  5950. // interface had better have the override. Otherwise, it's an error
  5951. // MIDL will not allow overloading names.
  5952. if (fDispInterface && pClass)
  5953. {
  5954. CString szPrimaryInterface;
  5955. Token *pPriInterf;
  5956. Token *pExclusiveMember;
  5957. szPrimaryInterface = pClass->GetTagValue(CLASS_INTERFACE);
  5958. pPriInterf = FindInterface(szPrimaryInterface);
  5959. // If working on non-primary interface make sure the property isn't overloaded on
  5960. // the primary, if so it better be marked exclusive.
  5961. if (_strcmpi(szInterfaceName, szPrimaryInterface))
  5962. {
  5963. pExclusiveMember = FindMethodInInterfaceWOPropDesc(pPriInterf, pChildToken, TRUE);
  5964. if (pExclusiveMember)
  5965. {
  5966. char szErrorText [ MAX_LINE_LEN+1 ];
  5967. if (pExclusiveMember->IsSet(PROPERTY_EXCLUSIVETOSCRIPT))
  5968. continue;
  5969. // Overloaded method -- illegal.
  5970. sprintf(szErrorText, "property %s:%s is overloaded - illegal.\n",
  5971. (LPCSTR)pClass->GetTagValue(CLASS_NAME),
  5972. (LPCSTR)pExclusiveMember->GetTagValue(PROPERTY_NAME));
  5973. ReportError(szErrorText);
  5974. return;
  5975. }
  5976. }
  5977. }
  5978. if ( pChildToken -> IsSet ( PROPERTY_SET ) )
  5979. {
  5980. #if COLLECT_STATISTICS==1
  5981. // Collect statistics on total number of property sets.
  5982. CollectStatistic(NUM_SETPROPERTY, GetStatistic(NUM_SETPROPERTY) + 1);
  5983. if (FindEnum ( pChildToken ))
  5984. CollectStatistic(NUM_SETENUMS, GetStatistic(NUM_SETENUMS) + 1);
  5985. #endif
  5986. // If it's an object valued property, generate a propputref,
  5987. // otherwise generate a propput
  5988. //
  5989. if ( pChildToken -> IsSet ( PROPERTY_OBJECT ) )
  5990. {
  5991. szArg = " [propputref";
  5992. }
  5993. else
  5994. {
  5995. szArg = " [propput";
  5996. }
  5997. if ( pChildToken -> IsSet ( PROPERTY_DISPID ) )
  5998. {
  5999. szArg += ", id(DISPID_";
  6000. szPropertyName = pChildToken->GetTagValue(PROPERTY_NAME);
  6001. if (pChildToken->IsSet(PROPERTY_NOPROPDESC))
  6002. {
  6003. if (pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE))
  6004. szPropertyName = pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE);
  6005. }
  6006. szPropertyName.ToUpper();
  6007. szArg += (LPCSTR)szInterfaceName;
  6008. szArg += "_";
  6009. szArg += (LPCSTR)szPropertyName;
  6010. szArg += ")";
  6011. }
  6012. pChildToken -> AddParam ( szArg, PROPERTY_DISPLAYBIND, "displaybind" );
  6013. pChildToken -> AddParam ( szArg, PROPERTY_BINDABLE, "bindable" );
  6014. pChildToken -> AddParam ( szArg, PROPERTY_HIDDEN, "hidden" );
  6015. pChildToken -> AddParam ( szArg, PROPERTY_RESTRICTED, "restricted" );
  6016. #ifndef WIN16_PARSER
  6017. pChildToken -> AddParam ( szArg, PROPERTY_NONBROWSABLE, "nonbrowsable" );
  6018. #endif
  6019. pChildToken -> AddParam ( szArg, PROPERTY_SOURCE, "source" );
  6020. if (pChildToken->IsSet(PROPERTY_NOPROPDESC) &&
  6021. pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE))
  6022. {
  6023. szPropertyName = pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE);
  6024. }
  6025. else
  6026. {
  6027. szPropertyName = pChildToken->GetTagValue(PROPERTY_NAME);
  6028. }
  6029. if (fDispInterface)
  6030. {
  6031. fprintf ( fpIDLFile, "%s] void %s(%s%s v);\n",
  6032. (LPCSTR)szArg, (LPCSTR)szPropertyName,
  6033. (LPCSTR)szProp, (LPCSTR)szAutomationType );
  6034. }
  6035. else
  6036. {
  6037. fprintf ( fpIDLFile, "%s] HRESULT %s(%s[in] %s v);\n",
  6038. (LPCSTR)szArg, (LPCSTR)szPropertyName,
  6039. (LPCSTR)szProp, (LPCSTR)szAutomationType );
  6040. }
  6041. }
  6042. if ( pChildToken -> IsSet ( PROPERTY_GET ) )
  6043. {
  6044. #if COLLECT_STATISTICS==1
  6045. // Collect statistics on total number of property sets.
  6046. CollectStatistic(NUM_GETPROPERTY, GetStatistic(NUM_GETPROPERTY) + 1);
  6047. if (FindEnum ( pChildToken ))
  6048. CollectStatistic(NUM_GETENUMS, GetStatistic(NUM_GETENUMS) + 1);
  6049. #endif
  6050. szArg = " [propget";
  6051. szArg += ", id(DISPID_";
  6052. szPropertyName = pChildToken->GetTagValue(PROPERTY_NAME);
  6053. if (pChildToken->IsSet(PROPERTY_NOPROPDESC))
  6054. {
  6055. if (pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE))
  6056. szPropertyName = pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE);
  6057. }
  6058. szPropertyName.ToUpper();
  6059. szArg += (LPCSTR)szInterfaceName;
  6060. szArg += "_";
  6061. szArg += (LPCSTR)szPropertyName;
  6062. szArg += ")";
  6063. pChildToken -> AddParam ( szArg, PROPERTY_DISPLAYBIND, "displaybind" );
  6064. pChildToken -> AddParam ( szArg, PROPERTY_BINDABLE, "bindable" );
  6065. pChildToken -> AddParam ( szArg, PROPERTY_HIDDEN, "hidden" );
  6066. pChildToken -> AddParam ( szArg, PROPERTY_RESTRICTED, "restricted" );
  6067. #ifndef WIN16_PARSER
  6068. pChildToken -> AddParam ( szArg, PROPERTY_NONBROWSABLE, "nonbrowsable" );
  6069. #endif
  6070. pChildToken -> AddParam ( szArg, PROPERTY_SOURCE, "source" );
  6071. if (pChildToken->IsSet(PROPERTY_NOPROPDESC) &&
  6072. pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE))
  6073. {
  6074. szPropertyName = pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE);
  6075. }
  6076. else
  6077. {
  6078. szPropertyName = pChildToken->GetTagValue(PROPERTY_NAME);
  6079. }
  6080. if (fDispInterface)
  6081. {
  6082. fprintf ( fpIDLFile, "%s] %s %s();\n",
  6083. (LPCSTR)szArg,
  6084. (LPCSTR)szAutomationType,
  6085. (LPCSTR)szPropertyName);
  6086. }
  6087. else
  6088. {
  6089. fprintf ( fpIDLFile, "%s] HRESULT %s(%s[retval, out] %s * p);\n",
  6090. (LPCSTR)szArg, (LPCSTR)szPropertyName,
  6091. (LPCSTR)szProp, (LPCSTR)szAutomationType );
  6092. }
  6093. }
  6094. }
  6095. }
  6096. }
  6097. void CPDLParser::GenerateMidlInterfaceDecl ( Token *pInterfaceToken, char *pszGUID,
  6098. char *pszSuper )
  6099. {
  6100. Token *pChildToken;
  6101. Token *pArgToken;
  6102. CString szArg;
  6103. CString szProp;
  6104. BOOL fFirst;
  6105. if ( pInterfaceToken -> GetType() == TYPE_EVENT )
  6106. return;
  6107. fprintf ( fpIDLFile, "[\n local,\n object,\n pointer_default(unique),\n" );
  6108. fprintf ( fpIDLFile, " uuid(%s)\n]\ninterface %s : %s\n{\n",
  6109. pInterfaceToken -> GetTagValue ( INTERFACE_GUID ),
  6110. pInterfaceToken -> GetTagValue ( INTERFACE_NAME ),
  6111. pInterfaceToken -> GetTagValue ( INTERFACE_SUPER ) );
  6112. CTokenListWalker ChildWalker ( pInterfaceToken );
  6113. while ( pChildToken = ChildWalker.GetNext() )
  6114. {
  6115. if ( pChildToken -> GetType() == TYPE_METHOD )
  6116. {
  6117. fprintf ( fpIDLFile, " %s %s(",
  6118. pChildToken -> GetTagValue ( METHOD_RETURNTYPE ),
  6119. pChildToken -> GetTagValue ( METHOD_NAME ) );
  6120. fFirst = TRUE;
  6121. CTokenListWalker ArgListWalker ( pChildToken );
  6122. while ( pArgToken = ArgListWalker.GetNext() )
  6123. {
  6124. szArg = "";
  6125. if ( !fFirst )
  6126. fprintf ( fpIDLFile, "," );
  6127. pArgToken -> AddParam ( szArg, METHODARG_IN, "in" );
  6128. pArgToken -> AddParam ( szArg, METHODARG_OUT, "out" );
  6129. fprintf ( fpIDLFile, "[%s] %s %s", (LPCSTR)szArg,
  6130. // Fixing a bug in the old code
  6131. // Should realy get the atype - allow the type if atype not set
  6132. pArgToken -> IsSet ( METHODARG_ATYPE ) ?
  6133. pArgToken -> GetTagValue ( METHODARG_ATYPE ) :
  6134. pArgToken -> GetTagValue ( METHODARG_TYPE ),
  6135. pArgToken -> GetTagValue ( METHODARG_ARGNAME ) );
  6136. fFirst = FALSE;
  6137. }
  6138. fprintf ( fpIDLFile, ");\n" );
  6139. }
  6140. else
  6141. {
  6142. // Property
  6143. ComputePropType ( pChildToken, szProp, FALSE );
  6144. if ( pChildToken -> IsSet ( PROPERTY_SET ))
  6145. {
  6146. fprintf ( fpIDLFile, " HRESULT put_%s(%s [in] %s v);\n",
  6147. (LPCSTR)pChildToken -> GetTagValue ( PROPERTY_NAME ),
  6148. (LPCSTR)szProp,
  6149. pChildToken -> GetTagValue ( PROPERTY_ATYPE) );
  6150. }
  6151. if ( pChildToken -> IsSet ( PROPERTY_GET ))
  6152. {
  6153. fprintf ( fpIDLFile,
  6154. " HRESULT get_%s(%s[out] %s * p);\n",
  6155. pChildToken -> GetTagValue ( PROPERTY_NAME ),
  6156. (LPCSTR)szProp,
  6157. pChildToken -> GetTagValue ( PROPERTY_ATYPE));
  6158. }
  6159. }
  6160. }
  6161. fprintf ( fpIDLFile, "}\n" );
  6162. }
  6163. BOOL CPDLParser::HasMondoDispInterface ( Token *pClassToken )
  6164. {
  6165. CTokenListWalker ChildWalker(pClassToken);
  6166. Token *pChildToken;
  6167. int cImplements = 0;
  6168. // Find out how many implements are in the class.
  6169. while (pChildToken = ChildWalker.GetNext())
  6170. {
  6171. if (pChildToken->GetType() == TYPE_IMPLEMENTS)
  6172. {
  6173. cImplements++;
  6174. }
  6175. }
  6176. // Any class with more than one implements a guid and a mondoguid will have
  6177. // a mondo dispinterface.
  6178. return (pClassToken->IsSet(CLASS_GUID) && cImplements && pClassToken->IsSet(CLASS_MONDOGUID));
  6179. }
  6180. void CPDLParser::GenerateCoClassDecl ( Token *pClassToken )
  6181. {
  6182. CString szName;
  6183. CString szDispName;
  6184. CString szInterfSuper;
  6185. BOOL fHasMondoDispInterface;
  6186. BOOL fElement = FALSE;
  6187. if (pClassToken->IsSet(CLASS_COCLASSNAME))
  6188. szName = pClassToken->GetTagValue(CLASS_COCLASSNAME);
  6189. else
  6190. szName = pClassToken->GetTagValue(CLASS_NAME);
  6191. fprintf(fpIDLFile, "[\n %suuid(%s)\n]\n",
  6192. pClassToken->IsSet(CLASS_CONTROL) ? "control,\n " : "",
  6193. pClassToken->GetTagValue(CLASS_GUID));
  6194. fprintf(fpIDLFile, "coclass %s\n{\n", (LPCSTR)szName );
  6195. fHasMondoDispInterface = HasMondoDispInterface(pClassToken);
  6196. if (fHasMondoDispInterface)
  6197. {
  6198. // Map to mondo dispinterface as default dispatch interface.
  6199. szDispName = (pClassToken->IsSet(CLASS_COCLASSNAME)) ?
  6200. pClassToken->GetTagValue (CLASS_COCLASSNAME) :
  6201. pClassToken->GetTagValue(CLASS_NAME);
  6202. }
  6203. else
  6204. {
  6205. // Map to the primary interface as default dispatch interface.
  6206. szDispName = pClassToken->GetTagValue(CLASS_INTERFACE);
  6207. }
  6208. fprintf(fpIDLFile, " [default] %sinterface %s%s;\n",
  6209. fHasMondoDispInterface ? "disp" : "",
  6210. fHasMondoDispInterface ? "Disp" : "",
  6211. (LPCSTR)szDispName);
  6212. if (pClassToken->IsSet(CLASS_EVENTS))
  6213. {
  6214. fprintf(fpIDLFile, " [source, default] dispinterface %s;\n",
  6215. pClassToken->GetTagValue(CLASS_EVENTS));
  6216. }
  6217. if (pClassToken->IsSet(CLASS_NONPRIMARYEVENTS1))
  6218. {
  6219. fprintf(fpIDLFile, " [source] dispinterface %s;\n",
  6220. pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS1));
  6221. }
  6222. if (pClassToken->IsSet(CLASS_NONPRIMARYEVENTS2))
  6223. {
  6224. fprintf(fpIDLFile, " [source] dispinterface %s;\n",
  6225. pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS2));
  6226. }
  6227. if (pClassToken->IsSet(CLASS_NONPRIMARYEVENTS3))
  6228. {
  6229. fprintf(fpIDLFile, " [source] dispinterface %s;\n",
  6230. pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS3));
  6231. }
  6232. if (pClassToken->IsSet(CLASS_NONPRIMARYEVENTS4))
  6233. {
  6234. fprintf(fpIDLFile, " [source] dispinterface %s;\n",
  6235. pClassToken->GetTagValue(CLASS_NONPRIMARYEVENTS4));
  6236. }
  6237. // Any other interface to expose in the coclass which is part of the primary
  6238. // interface?
  6239. CTokenListWalker ChildWalker(pClassToken);
  6240. Token *pChildToken;
  6241. while (pChildToken = ChildWalker.GetNext())
  6242. {
  6243. if (pChildToken->GetType() == TYPE_IMPLEMENTS)
  6244. {
  6245. Token *pInterf;
  6246. CString szInterface;
  6247. if (!fElement)
  6248. fElement = !_stricmp((LPSTR)pChildToken->GetTagValue(IMPLEMENTS_NAME), "IHTMLElement");
  6249. szInterface = pChildToken->GetTagValue(IMPLEMENTS_NAME);
  6250. pInterf = FindInterface(szInterface);
  6251. if (pInterf)
  6252. {
  6253. // Is the interface a local one if not then don't check, we
  6254. // only need to check where interfaces are actually used.
  6255. if (FindInterfaceLocally(szInterface))
  6256. {
  6257. // If the super isn't specified and it's not a primary interface
  6258. // then error the super is required for non-primary interfaces.
  6259. if (_stricmp((LPSTR)pClassToken->GetTagValue(CLASS_INTERFACE),
  6260. (LPSTR)pInterf->GetTagValue(INTERFACE_NAME)) &&
  6261. !pInterf->IsSet(INTERFACE_SUPER) &&
  6262. !IsPrimaryInterface(szInterface))
  6263. {
  6264. char szErrorText [ MAX_LINE_LEN+1 ];
  6265. sprintf(szErrorText, "Interface %s missing super key.\n",
  6266. (LPSTR)pInterf->GetTagValue(INTERFACE_NAME));
  6267. ReportError(szErrorText);
  6268. return;
  6269. }
  6270. }
  6271. fprintf(fpIDLFile, " interface %s;\n",
  6272. (LPCSTR)pInterf->GetTagValue(INTERFACE_NAME));
  6273. }
  6274. }
  6275. }
  6276. fprintf(fpIDLFile, "};\n");
  6277. fprintf(fpIDLFile, "cpp_quote(\"EXTERN_C const GUID CLSID_%s;\")\n",
  6278. pClassToken->GetTagValue(CLASS_NAME));
  6279. if (!pClassToken->IsSet(CLASS_EVENTS) && fElement)
  6280. {
  6281. char szErrorText [ MAX_LINE_LEN+1 ];
  6282. sprintf(szErrorText, "Class %s missing events key.\n", pClassToken->GetTagValue(CLASS_NAME));
  6283. ReportError(szErrorText);
  6284. return;
  6285. }
  6286. }
  6287. void CPDLParser::GenerateEnumDescIDL ( Token *pEnumToken )
  6288. {
  6289. Token *pEvalToken;
  6290. CString szName;
  6291. fprintf ( fpIDLFile, "\ntypedef [uuid(%s)] enum _%s {\n" ,
  6292. pEnumToken -> GetTagValue ( ENUM_GUID ),
  6293. pEnumToken -> GetTagValue ( ENUM_NAME ) );
  6294. CTokenListWalker EvalChildList ( pEnumToken );
  6295. while ( pEvalToken = EvalChildList.GetNext() )
  6296. {
  6297. if ( pEvalToken -> IsSet ( EVAL_ODLNAME ) )
  6298. {
  6299. szName = pEvalToken -> GetTagValue ( EVAL_ODLNAME );
  6300. }
  6301. else
  6302. {
  6303. szName = pEnumToken -> GetTagValue ( ENUM_NAME );
  6304. szName += pEvalToken -> GetTagValue ( EVAL_NAME );
  6305. }
  6306. fprintf ( fpIDLFile, " [helpstring(\"%s\")] %s = %s,\n",
  6307. pEvalToken -> IsSet ( EVAL_STRING ) ?
  6308. pEvalToken -> GetTagValue ( EVAL_STRING ) :
  6309. pEvalToken -> GetTagValue ( EVAL_NAME ),
  6310. (LPCSTR)szName,
  6311. pEvalToken -> GetTagValue ( EVAL_VALUE ) );
  6312. }
  6313. fprintf ( fpIDLFile, "}%s;\n",
  6314. pEnumToken -> GetTagValue ( ENUM_NAME ) );
  6315. }
  6316. void CPDLParser::ReportError ( LPCSTR szErrorString )
  6317. {
  6318. printf ( "%s(0) : error PDL0000: %s", _pszPDLFileName, szErrorString);
  6319. fprintf ( fpLOGFile, "%s(0) : error PDL0000: %s", _pszPDLFileName, szErrorString );
  6320. }
  6321. void CPDLParser::GenerateHeaderFile ( void )
  6322. {
  6323. CTokenListWalker ThisFileList ( pRuntimeList, _pszPDLFileName );
  6324. Token *pImportToken;
  6325. Token *pInterfaceToken;
  6326. Token *pClassToken;
  6327. Token *pEnumToken;
  6328. Token *pStructToken;
  6329. char *pStr;
  6330. CString szCoClassName;
  6331. char szName [ MAX_LINE_LEN+1 ];
  6332. CString szInterfaceName;
  6333. strcpy ( szName, _pszPDLFileName );
  6334. pStr = strstr ( szName, "." );
  6335. if ( pStr )
  6336. *pStr = '\0';
  6337. _strlwr ( szName );
  6338. fprintf ( fpHeaderFile, "#ifndef __%s_h__\n", szName );
  6339. fprintf ( fpHeaderFile, "#define __%s_h__\n\n", szName );
  6340. fprintf ( fpHeaderFile, "/* Forward Declarations */\n" );
  6341. fprintf ( fpHeaderFile, "\nstruct ENUMDESC;\n" );
  6342. // For each import, generate a .h include
  6343. while ( pImportToken = ThisFileList.GetNext ( TYPE_IMPORT ) )
  6344. {
  6345. fprintf ( fpHeaderFile, "\n/* header files for imported files */\n" );
  6346. GenerateIncludeStatement ( pImportToken );
  6347. }
  6348. ThisFileList.Reset();
  6349. // Forward define all the interfaces so we can have defined them in any order
  6350. while ( pInterfaceToken = ThisFileList.GetNext ( TYPE_INTERFACE ) )
  6351. {
  6352. szInterfaceName = pInterfaceToken -> GetTagValue ( INTERFACE_NAME );
  6353. if ( szInterfaceName != "IDispatch" &&
  6354. szInterfaceName != "IUnknown" )
  6355. {
  6356. fprintf ( fpHeaderFile, "\n#ifndef __%s_FWD_DEFINED__\n",
  6357. pInterfaceToken -> GetTagValue ( INTERFACE_NAME ) );
  6358. fprintf ( fpHeaderFile, "#define __%s_FWD_DEFINED__\n",
  6359. pInterfaceToken -> GetTagValue ( INTERFACE_NAME ) );
  6360. fprintf ( fpHeaderFile, "typedef interface %s %s;\n",
  6361. pInterfaceToken -> GetTagValue ( INTERFACE_NAME ),
  6362. pInterfaceToken -> GetTagValue ( INTERFACE_NAME ) ) ;
  6363. fprintf ( fpHeaderFile, "#endif /* __%s_FWD_DEFINED__ */\n",
  6364. pInterfaceToken -> GetTagValue ( INTERFACE_NAME ) );
  6365. }
  6366. }
  6367. //
  6368. // Generate all the enums
  6369. //
  6370. ThisFileList.Reset();
  6371. while ( pEnumToken = ThisFileList.GetNext ( TYPE_ENUM ) )
  6372. {
  6373. GenerateIncludeEnum(pEnumToken, TRUE);
  6374. }
  6375. //
  6376. // Generate all the structs
  6377. //
  6378. ThisFileList.Reset();
  6379. while (pStructToken = ThisFileList.GetNext(TYPE_STRUCT))
  6380. {
  6381. GenerateStruct(pStructToken, fpHeaderFile);
  6382. }
  6383. ThisFileList.Reset();
  6384. // For each interface generate an extern for the GUID &
  6385. // an interface decl
  6386. while ( pInterfaceToken = ThisFileList.GetNext ( TYPE_INTERFACE ) )
  6387. {
  6388. szInterfaceName = pInterfaceToken -> GetTagValue ( INTERFACE_NAME );
  6389. if ( szInterfaceName != "IDispatch" &&
  6390. szInterfaceName != "IUnknown" &&
  6391. !pInterfaceToken -> IsSet ( INTERFACE_ABSTRACT ) &&
  6392. pInterfaceToken -> IsSet ( INTERFACE_GUID ) )
  6393. {
  6394. GenerateIncludeInterface ( pInterfaceToken );
  6395. }
  6396. }
  6397. ThisFileList.Reset();
  6398. // For each class with a GUID, generate a GUID ref
  6399. while ( pClassToken = ThisFileList.GetNext ( TYPE_CLASS ) )
  6400. {
  6401. if ( pClassToken -> IsSet ( CLASS_GUID ) &&
  6402. !pClassToken -> IsSet ( CLASS_ABSTRACT ) )
  6403. {
  6404. pClassToken -> GetTagValueOrDefault ( szCoClassName,
  6405. CLASS_COCLASSNAME, pClassToken -> GetTagValue ( CLASS_NAME ) );
  6406. fprintf ( fpHeaderFile, "\n\nEXTERN_C const GUID GUID_%s;\n\n",
  6407. pClassToken -> GetTagValue ( CLASS_COCLASSNAME ) );
  6408. if ( HasMondoDispInterface ( pClassToken ) )
  6409. {
  6410. CString szDispName;
  6411. // Map to mondo dispinterface as default dispatch interface.
  6412. szDispName = (pClassToken->IsSet(CLASS_COCLASSNAME)) ?
  6413. pClassToken->GetTagValue (CLASS_COCLASSNAME) :
  6414. pClassToken->GetTagValue(CLASS_NAME);
  6415. fprintf(fpHeaderFile, "\n\nEXTERN_C const GUID DIID_Disp%s;\n\n",
  6416. (LPCSTR)szDispName);
  6417. }
  6418. }
  6419. // Also generate extern definitions for all propdescs in this file
  6420. GeneratePropdescExtern ( pClassToken, FALSE /* Don't recurse */ );
  6421. }
  6422. fprintf ( fpHeaderFile, "\n\n#endif /*__%s_h__*/\n\n", szName );
  6423. }
  6424. void CPDLParser::GenerateIncludeStatement ( Token *pImportToken )
  6425. {
  6426. char szText [ MAX_LINE_LEN+1 ];
  6427. char *pStr;
  6428. strcpy ( szText, pImportToken -> GetTagValue ( IMPORT_NAME ) );
  6429. if ( pStr = strstr ( szText, "." ) )
  6430. {
  6431. strcpy ( pStr, ".h" );
  6432. }
  6433. else
  6434. {
  6435. strcat ( szText, ".h" );
  6436. }
  6437. fprintf ( fpHeaderFile, "#include \"%s\"\n", szText );
  6438. }
  6439. void CPDLParser::GenerateIncludeInterface ( Token *pInterfaceToken )
  6440. {
  6441. // Only generate the C++ Form
  6442. Token *pChildToken;
  6443. Token *pArgToken;
  6444. CString szArg;
  6445. CString szProp;
  6446. BOOL fFirst;
  6447. CString szSuper;
  6448. if ( pInterfaceToken -> GetType() == TYPE_EVENT )
  6449. return;
  6450. fprintf ( fpHeaderFile, "\n#ifndef __%s_INTERFACE_DEFINED__\n",
  6451. pInterfaceToken -> GetTagValue ( INTERFACE_NAME ) );
  6452. fprintf ( fpHeaderFile, "\n#define __%s_INTERFACE_DEFINED__\n",
  6453. pInterfaceToken -> GetTagValue ( INTERFACE_NAME ) );
  6454. fprintf ( fpHeaderFile, "\nEXTERN_C const IID IID_%s;\n\n",
  6455. pInterfaceToken -> GetTagValue ( INTERFACE_NAME ) );
  6456. if (pInterfaceToken->IsSet(INTERFACE_CUSTOM) ||
  6457. !PrimaryTearoff(pInterfaceToken) ||
  6458. !_stricmp((LPCSTR)pInterfaceToken->GetTagValue(INTERFACE_NAME), "IHTMLDocument2"))
  6459. {
  6460. szSuper = pInterfaceToken->GetTagValue(INTERFACE_SUPER);
  6461. }
  6462. fprintf(fpHeaderFile, "\nMIDL_INTERFACE(\"%s\")\n%s : public %s\n{\npublic:\n",
  6463. pInterfaceToken->GetTagValue(INTERFACE_GUID),
  6464. pInterfaceToken->GetTagValue(INTERFACE_NAME),
  6465. ((LPCSTR)szSuper && *(LPCSTR)szSuper) ? (LPCSTR)szSuper : "IDispatch");
  6466. CTokenListWalker ChildWalker ( pInterfaceToken );
  6467. while ( pChildToken = ChildWalker.GetNext() )
  6468. {
  6469. if ( pChildToken -> GetType() == TYPE_METHOD )
  6470. {
  6471. fprintf ( fpHeaderFile, " virtual %s STDMETHODCALLTYPE %s(\n ",
  6472. pChildToken -> GetTagValue ( METHOD_RETURNTYPE ),
  6473. pChildToken->IsSet(METHOD_SZINTERFACEEXPOSE) ?
  6474. pChildToken->GetTagValue(METHOD_SZINTERFACEEXPOSE) :
  6475. pChildToken->GetTagValue(METHOD_NAME));
  6476. fFirst = TRUE;
  6477. CTokenListWalker ArgListWalker ( pChildToken );
  6478. while ( pArgToken = ArgListWalker.GetNext() )
  6479. {
  6480. if ( !fFirst )
  6481. fprintf ( fpHeaderFile, "," );
  6482. szArg = "";
  6483. pArgToken -> AddParam ( szArg, METHODARG_IN, "in" );
  6484. pArgToken -> AddParam ( szArg, METHODARG_OUT, "out" );
  6485. fprintf ( fpHeaderFile, "/* [%s] */ %s %s", (LPCSTR)szArg,
  6486. // Fixing a bug in the old code
  6487. // Should realy get the atype - allow the type if atype not set
  6488. ConvertType(pArgToken -> IsSet ( METHODARG_ATYPE ) ?
  6489. pArgToken -> GetTagValue ( METHODARG_ATYPE ) :
  6490. pArgToken -> GetTagValue ( METHODARG_TYPE )),
  6491. pArgToken -> GetTagValue ( METHODARG_ARGNAME ) );
  6492. fFirst = FALSE;
  6493. }
  6494. fprintf ( fpHeaderFile, ") = 0;\n\n" );
  6495. }
  6496. else
  6497. {
  6498. // Property
  6499. ComputePropType(pChildToken, szProp, TRUE);
  6500. if ( pChildToken -> IsSet ( PROPERTY_SET ))
  6501. {
  6502. fprintf ( fpHeaderFile, " virtual HRESULT STDMETHODCALLTYPE put_%s(\n %s /* [in] */ %s v) = 0;\n\n",
  6503. pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
  6504. (LPSTR)pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
  6505. (LPSTR)pChildToken->GetTagValue(PROPERTY_NAME),
  6506. (LPCSTR)szProp,
  6507. pChildToken -> GetTagValue ( PROPERTY_ATYPE));
  6508. }
  6509. if ( pChildToken -> IsSet ( PROPERTY_GET ))
  6510. {
  6511. fprintf ( fpHeaderFile,
  6512. " virtual HRESULT STDMETHODCALLTYPE get_%s(\n %s /* [out] */ %s * p) = 0;\n\n",
  6513. pChildToken->IsSet(PROPERTY_SZINTERFACEEXPOSE) ?
  6514. (LPSTR)pChildToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE) :
  6515. (LPSTR)pChildToken->GetTagValue(PROPERTY_NAME),
  6516. (LPCSTR)szProp,
  6517. pChildToken -> GetTagValue ( PROPERTY_ATYPE) );
  6518. }
  6519. }
  6520. }
  6521. fprintf ( fpHeaderFile, "};\n\n" );
  6522. fprintf ( fpHeaderFile, "#endif /* __%s_INTERFACE_DEFINED__ */\n\n",
  6523. pInterfaceToken -> GetTagValue ( INTERFACE_NAME ) );
  6524. }
  6525. void CPDLParser::GenerateIncludeEnum(
  6526. Token *pEnumToken, BOOL fSpitExtern, FILE *pFile)
  6527. {
  6528. Token *pEvalToken;
  6529. if (!pFile)
  6530. {
  6531. pFile = fpHeaderFile;
  6532. }
  6533. fprintf(pFile, "typedef enum _%s\n{\n" ,
  6534. pEnumToken -> GetTagValue ( ENUM_NAME ) );
  6535. CTokenListWalker EvalChildList ( pEnumToken );
  6536. while ( pEvalToken = EvalChildList.GetNext() )
  6537. {
  6538. fprintf(pFile, " %s%s = %s,\n",
  6539. pEnumToken -> GetTagValue(ENUM_PREFIX),
  6540. pEvalToken -> GetTagValue(EVAL_NAME),
  6541. pEvalToken -> GetTagValue(EVAL_VALUE));
  6542. }
  6543. // Add an _Max for the MAC build - apparently the mac needs
  6544. // this to indicate that it's an integer
  6545. fprintf(pFile, " %s_Max = 2147483647L\n",
  6546. pEnumToken -> GetTagValue ( ENUM_NAME ) );
  6547. fprintf(pFile, "} %s;\n\n",
  6548. pEnumToken -> GetTagValue ( ENUM_NAME ) );
  6549. if (fSpitExtern)
  6550. {
  6551. // Generate an EXTERN from the enum descriptor so other hdls only have to include
  6552. // the .h file.
  6553. fprintf(pFile, "\nEXTERN_C const ENUMDESC s_enumdesc%s;\n\n",
  6554. pEnumToken->GetTagValue ( ENUM_NAME ) );
  6555. }
  6556. }
  6557. void
  6558. CPDLParser::GenerateStruct(Token *pStructToken, FILE *pFile)
  6559. {
  6560. Token *pMemberToken;
  6561. fprintf(pFile, "typedef struct _%s\n{\n" ,
  6562. pStructToken->GetTagValue(STRUCT_NAME));
  6563. CTokenListWalker ChildList(pStructToken);
  6564. while (pMemberToken = ChildList.GetNext())
  6565. {
  6566. fprintf(pFile, " %s %s;\n",
  6567. pMemberToken->GetTagValue(STRUCTMEMBER_TYPE),
  6568. pMemberToken->GetTagValue(STRUCTMEMBER_NAME));
  6569. }
  6570. fprintf(pFile, "} %s;\n\n",
  6571. pStructToken->GetTagValue(STRUCT_NAME));
  6572. }
  6573. BOOL CPDLParser::AddType ( LPCSTR szTypeName, LPCSTR szHandler )
  6574. {
  6575. Token *pTypeToken = pDynamicTypeList->AddNewToken ( (DESCRIPTOR_TYPE)TYPE_DATATYPE );
  6576. if ( pTypeToken == NULL )
  6577. return FALSE;
  6578. if ( !pTypeToken->AddTag ( DATATYPE_NAME, szTypeName ) )
  6579. return FALSE;
  6580. return pTypeToken->AddTag ( DATATYPE_HANDLER, szHandler );
  6581. }
  6582. BOOL CPDLParser::AddEventType ( LPCSTR szTypeName, LPCSTR szVTSType )
  6583. {
  6584. Token *pTypeToken = pDynamicEventTypeList->AddNewToken ( (DESCRIPTOR_TYPE)TYPE_DATATYPE );
  6585. if ( pTypeToken == NULL )
  6586. return FALSE;
  6587. if ( !pTypeToken->AddTag ( DATATYPE_NAME, szTypeName ) )
  6588. return FALSE;
  6589. return pTypeToken->AddTag ( DATATYPE_HANDLER, szVTSType );
  6590. }
  6591. BOOL CPDLParser::LookupType ( LPCSTR szTypeName, CString &szIntoString,
  6592. CString &szFnPrefix, StorageType *pStorageType /* = NULL */ )
  6593. {
  6594. Token *pTypeToken;
  6595. UINT uIndex;
  6596. // Look in the static array first
  6597. if ( ( uIndex = szIntoString.Lookup ( DataTypes, szTypeName ) ) != (UINT)-1 )
  6598. {
  6599. if ( pStorageType )
  6600. {
  6601. *pStorageType = DataTypes [ uIndex ].stStorageType;
  6602. szFnPrefix = DataTypes [ uIndex ].szMethodFnPrefix;
  6603. }
  6604. return TRUE;
  6605. }
  6606. // Look finaly in the dynamic array
  6607. CTokenListWalker TypeList ( pDynamicTypeList );
  6608. if ( pTypeToken = TypeList.GetNext ( (DESCRIPTOR_TYPE)TYPE_DATATYPE, szTypeName ) )
  6609. {
  6610. szIntoString = pTypeToken->GetTagValue ( DATATYPE_HANDLER );
  6611. if ( pStorageType )
  6612. {
  6613. // In the dynamic array are either enums iface ptrs or class ptrs
  6614. // All can be stored in a DWORD, so ...
  6615. *pStorageType = STORAGETYPE_NUMBER;
  6616. }
  6617. return TRUE;
  6618. }
  6619. else
  6620. {
  6621. return FALSE;
  6622. }
  6623. }
  6624. BOOL CPDLParser::LookupEventType ( CString &szIntoString, LPCSTR szTypeName )
  6625. {
  6626. Token *pTypeToken;
  6627. // Look in the static array first
  6628. if ( szIntoString.Lookup ( vt, szTypeName ) != (UINT)-1 )
  6629. {
  6630. return TRUE;
  6631. }
  6632. // Look finaly in the dynamic array
  6633. CTokenListWalker TypeList ( pDynamicEventTypeList );
  6634. if ( pTypeToken = TypeList.GetNext ( (DESCRIPTOR_TYPE)TYPE_DATATYPE, szTypeName ) )
  6635. {
  6636. szIntoString = pTypeToken->GetTagValue ( DATATYPE_HANDLER );
  6637. return TRUE;
  6638. }
  6639. else
  6640. {
  6641. return FALSE;
  6642. }
  6643. }
  6644. UINT uProps [] =
  6645. {
  6646. PROPERTY_MEMBER,
  6647. PROPERTY_ABSTRACT,
  6648. PROPERTY_GETSETMETHODS,
  6649. PROPERTY_CAA,
  6650. PROPERTY_SUBOBJECT
  6651. };
  6652. // Legal combinations of properties
  6653. static struct
  6654. {
  6655. UINT uID1;
  6656. UINT uID2;
  6657. UINT uID3;
  6658. UINT uMask;
  6659. } PropertyCheck [] =
  6660. {
  6661. { PROPERTY_MEMBER, (UINT)-1,(UINT)-1 },
  6662. { PROPERTY_SUBOBJECT, (UINT)-1 ,(UINT)-1 },
  6663. { PROPERTY_SUBOBJECT, PROPERTY_MEMBER,(UINT)-1 },
  6664. { PROPERTY_GETSETMETHODS, (UINT)-1,(UINT)-1 },
  6665. { PROPERTY_ABSTRACT, (UINT)-1,(UINT)-1},
  6666. { PROPERTY_CAA, (UINT)-1,(UINT)-1 },
  6667. { PROPERTY_SUBOBJECT, PROPERTY_CAA,(UINT)-1 },
  6668. };
  6669. void CPDLParser::Init ( void )
  6670. {
  6671. UINT i,j;
  6672. for ( i = 0 ; i < ARRAY_SIZE ( PropertyCheck ) ; i++ )
  6673. {
  6674. PropertyCheck [ i ].uMask = 0;
  6675. for ( j = 0 ; j < ARRAY_SIZE ( uProps ) ; j++ )
  6676. {
  6677. if ( PropertyCheck [ i ].uID1 == uProps [ j ] )
  6678. {
  6679. PropertyCheck [ i ].uMask |= 1<<j;
  6680. }
  6681. else if ( PropertyCheck [ i ].uID2 == uProps [ j ] )
  6682. {
  6683. PropertyCheck [ i ].uMask |= 1<<j;
  6684. }
  6685. else if ( PropertyCheck [ i ].uID3 == uProps [ j ] )
  6686. {
  6687. PropertyCheck [ i ].uMask |= 1<<j;
  6688. }
  6689. }
  6690. }
  6691. }
  6692. BOOL CPDLParser::PatchPropertyTypes ( void )
  6693. {
  6694. // For each property declaration, set the object flag if the
  6695. // Handler for the type is object
  6696. CTokenListWalker WholeList ( pRuntimeList );
  6697. Token *pToken;
  6698. Token *pChildToken;
  6699. CString szHandler;
  6700. CString szFnPrefix;
  6701. CString szAType;
  6702. CString szName;
  6703. BOOL fMatched;
  6704. char szErrorText [ MAX_LINE_LEN+1 ];
  6705. UINT i;
  6706. UINT uMask;
  6707. while ( pToken = WholeList.GetNext() )
  6708. {
  6709. if ( pToken -> GetType() == TYPE_EVENT ||
  6710. pToken -> GetType() == TYPE_CLASS ||
  6711. pToken -> GetType() == TYPE_INTERFACE )
  6712. {
  6713. if ( pToken -> GetType() == TYPE_CLASS )
  6714. {
  6715. // Has it got a super, if so is it referenced
  6716. if ( pToken -> IsSet ( CLASS_SUPER ) )
  6717. {
  6718. CTokenListWalker AllList ( pRuntimeList );
  6719. if ( !AllList.GetNext ( TYPE_CLASS, pToken -> GetTagValue ( CLASS_SUPER ) ) )
  6720. {
  6721. sprintf ( szErrorText, "Class %s References unknown super:%s\n",
  6722. (LPCSTR)pToken->GetTagValue ( CLASS_NAME ),
  6723. (LPCSTR)pToken->GetTagValue ( CLASS_SUPER ) );
  6724. ReportError ( szErrorText );
  6725. return FALSE;
  6726. }
  6727. }
  6728. if ( pToken -> IsSet ( CLASS_INTERFACE ) )
  6729. {
  6730. CTokenListWalker AllList ( pRuntimeList );
  6731. if ( !AllList.GetNext ( TYPE_INTERFACE, pToken -> GetTagValue ( CLASS_INTERFACE ) ) )
  6732. {
  6733. sprintf ( szErrorText, "Class %s References unknown interface:%s\n",
  6734. (LPCSTR)pToken->GetTagValue ( CLASS_NAME ),
  6735. (LPCSTR)pToken->GetTagValue ( CLASS_INTERFACE ) );
  6736. ReportError ( szErrorText );
  6737. return FALSE;
  6738. }
  6739. }
  6740. if ( pToken -> IsSet ( CLASS_EVENTS ) )
  6741. {
  6742. CTokenListWalker AllList ( pRuntimeList );
  6743. if ( !AllList.GetNext ( TYPE_EVENT, pToken -> GetTagValue ( CLASS_EVENTS ) ) )
  6744. {
  6745. sprintf ( szErrorText, "Class %s References unknown events:%s\n",
  6746. (LPCSTR)pToken->GetTagValue ( CLASS_NAME ),
  6747. (LPCSTR)pToken->GetTagValue ( CLASS_EVENTS ) );
  6748. ReportError ( szErrorText );
  6749. return FALSE;
  6750. }
  6751. }
  6752. // If you have an event set , you must have a coclass
  6753. if ( pToken -> IsSet ( CLASS_EVENTS ) && !pToken -> IsSet ( CLASS_ABSTRACT ) &&
  6754. !pToken -> IsSet ( CLASS_GUID ) )
  6755. {
  6756. sprintf ( szErrorText, "Non abstract class %s has an event set but no GUID\n",
  6757. (LPCSTR)pToken->GetTagValue ( CLASS_NAME ) );
  6758. ReportError ( szErrorText );
  6759. return FALSE;
  6760. }
  6761. }
  6762. else if ( pToken -> GetType() == TYPE_INTERFACE )
  6763. {
  6764. if ( pToken -> IsSet ( INTERFACE_SUPER ) )
  6765. {
  6766. CTokenListWalker AllList ( pRuntimeList );
  6767. if ( !AllList.GetNext ( TYPE_INTERFACE, pToken -> GetTagValue ( INTERFACE_SUPER ) ) )
  6768. {
  6769. sprintf ( szErrorText, "Interface %s References unknown super:%s\n",
  6770. (LPCSTR)pToken->GetTagValue ( INTERFACE_NAME ),
  6771. (LPCSTR)pToken->GetTagValue ( INTERFACE_SUPER ) );
  6772. ReportError ( szErrorText );
  6773. return FALSE;
  6774. }
  6775. }
  6776. }
  6777. else if ( pToken -> GetType() == TYPE_EVENT )
  6778. {
  6779. if ( pToken -> IsSet ( EVENT_SUPER ) )
  6780. {
  6781. CTokenListWalker AllList ( pRuntimeList );
  6782. if ( !AllList.GetNext ( TYPE_EVENT, pToken -> GetTagValue ( EVENT_SUPER ) ) )
  6783. {
  6784. sprintf ( szErrorText, "Events %s References unknown super:%s\n",
  6785. (LPCSTR)pToken->GetTagValue ( EVENT_NAME ),
  6786. (LPCSTR)pToken->GetTagValue ( EVENT_SUPER ) );
  6787. ReportError ( szErrorText );
  6788. return FALSE;
  6789. }
  6790. }
  6791. }
  6792. CTokenListWalker ChildList ( pToken );
  6793. while ( pChildToken = ChildList.GetNext() )
  6794. {
  6795. if ( pChildToken -> GetType() == TYPE_PROPERTY )
  6796. {
  6797. // If the Type field is not set, which it won't be for many
  6798. // abstract properties, set it to the ATYPE. We still
  6799. // need the type to determine if the property is an object value
  6800. // property
  6801. if ( !pChildToken -> IsSet ( PROPERTY_TYPE ) )
  6802. {
  6803. pChildToken -> AddTag ( PROPERTY_TYPE,
  6804. pChildToken -> GetTagValue ( PROPERTY_ATYPE ) );
  6805. }
  6806. if ( !LookupType ( pChildToken -> GetTagValue ( PROPERTY_TYPE ),
  6807. szHandler, szFnPrefix ) )
  6808. {
  6809. // Seeing as we don't use the handler for abstract types, we
  6810. // allow the lookup to fail
  6811. if ( !pChildToken -> IsSet ( PROPERTY_ABSTRACT ) )
  6812. {
  6813. sprintf ( szErrorText, "Invalid Type:%s in %s Property:%s\n",
  6814. (LPCSTR)pChildToken->GetTagValue ( PROPERTY_TYPE ),
  6815. (LPCSTR)pToken->GetTagValue ( NAME_TAG ),
  6816. (LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ) );
  6817. ReportError ( szErrorText );
  6818. return FALSE;
  6819. }
  6820. }
  6821. // Currently we insist that you automate enums as BSTR's
  6822. szAType = pChildToken->GetTagValue ( PROPERTY_ATYPE );
  6823. if ( szHandler == "Enum" && szAType != "BSTR" )
  6824. {
  6825. sprintf ( szErrorText, "You must set atype:BSTR for an enum property %s : Property:%s\n",
  6826. (LPCSTR)pToken->GetTagValue ( NAME_TAG ),
  6827. (LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ) );
  6828. ReportError ( szErrorText );
  6829. return FALSE;
  6830. }
  6831. if ( szHandler == "Color" && szAType != "VARIANT" )
  6832. {
  6833. sprintf ( szErrorText, "You must set atype:VARIANT for an type:CColorValue property %s : Property:%s\n",
  6834. (LPCSTR)pToken->GetTagValue ( NAME_TAG ),
  6835. (LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ) );
  6836. ReportError ( szErrorText );
  6837. return FALSE;
  6838. }
  6839. if ( szHandler == "object" &&
  6840. !pChildToken -> IsSet ( PROPERTY_OBJECT ) )
  6841. {
  6842. pChildToken -> Set ( PROPERTY_OBJECT );
  6843. }
  6844. // Object valued properties must always be abstract because we don't have
  6845. // the notion of an "ObjectHandler"
  6846. if ( pChildToken -> IsSet ( PROPERTY_OBJECT ) &&
  6847. !pChildToken -> IsSet ( PROPERTY_ABSTRACT ) )
  6848. {
  6849. sprintf ( szErrorText, "Object Type Property %s:%s MUST be abstract\n",
  6850. (LPCSTR)pToken->GetTagValue ( NAME_TAG ),
  6851. (LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ) );
  6852. ReportError ( szErrorText );
  6853. return FALSE;
  6854. }
  6855. for ( i = 0, uMask = 0 ; i < ARRAY_SIZE ( uProps ) ; i++ )
  6856. {
  6857. if ( pChildToken -> IsSet ( uProps [ i ] ) )
  6858. {
  6859. uMask |= 1<<i;
  6860. }
  6861. }
  6862. for ( i = 0, fMatched = FALSE;
  6863. i < ARRAY_SIZE ( PropertyCheck ); i++ )
  6864. {
  6865. if ( PropertyCheck [ i ].uMask == uMask )
  6866. {
  6867. fMatched = TRUE;
  6868. }
  6869. }
  6870. if ( !fMatched )
  6871. {
  6872. sprintf ( szErrorText, "Invalid combination of member/method/abstract/caa on %s:%s\n",
  6873. (LPCSTR)pToken->GetTagValue ( NAME_TAG ),
  6874. (LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ) );
  6875. ReportError ( szErrorText );
  6876. return FALSE;
  6877. }
  6878. // Subobject MUST have a GET and MUST NOT have a SET
  6879. if ( pChildToken -> IsSet ( PROPERTY_SUBOBJECT ) &&
  6880. ( !pChildToken -> IsSet ( PROPERTY_GET ) || pChildToken -> IsSet ( PROPERTY_SET ) ) )
  6881. {
  6882. sprintf ( szErrorText, "Invalid combination of subobject/get/set on %s:%s\n",
  6883. (LPCSTR)pToken->GetTagValue ( NAME_TAG ),
  6884. (LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ) );
  6885. ReportError ( szErrorText );
  6886. return FALSE;
  6887. }
  6888. // DISPLAYBIND Always implies BINDABLE - so always set it
  6889. if ( pChildToken -> IsSet ( PROPERTY_DISPLAYBIND ) &&
  6890. !pChildToken -> IsSet ( PROPERTY_BINDABLE ) )
  6891. {
  6892. pChildToken -> Set ( PROPERTY_BINDABLE );
  6893. }
  6894. // For now we limit the enum: type to atypre:VARIANT,
  6895. if ( pChildToken -> IsSet ( PROPERTY_ENUMREF ) )
  6896. {
  6897. if ( szAType != "VARIANT" )
  6898. {
  6899. sprintf ( szErrorText, "Invalid combination of atype/enum on %s:%s\n",
  6900. (LPCSTR)pToken->GetTagValue ( NAME_TAG ),
  6901. (LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ) );
  6902. ReportError ( szErrorText );
  6903. return FALSE;
  6904. }
  6905. }
  6906. // Set an internal flag if the property cascades - saves looking this up later
  6907. if ( pChildToken -> IsSet ( PROPERTY_CAA ) )
  6908. {
  6909. const CCachedAttrArrayInfo *pCCAAI = GetCachedAttrArrayInfo( (LPCSTR)pChildToken -> GetTagValue ( PROPERTY_DISPID ) );
  6910. if ( pCCAAI->szDispId != NULL )
  6911. {
  6912. pChildToken -> Set ( PROPERTY_CASCADED );
  6913. }
  6914. }
  6915. if ( !pChildToken -> IsSet ( PROPERTY_DISPID ) )
  6916. {
  6917. sprintf ( szErrorText, "Missing compulsory attribute 'dispid' on %s:%s\n",
  6918. (LPCSTR)pToken->GetTagValue ( NAME_TAG ),
  6919. (LPCSTR)pChildToken->GetTagValue ( PROPERTY_NAME ) );
  6920. ReportError ( szErrorText );
  6921. }
  6922. // SETATDESIGNTIME augments regular set
  6923. if ( pChildToken -> IsSet ( PROPERTY_SETDESIGNMODE ) )
  6924. {
  6925. pChildToken -> Set ( PROPERTY_SET );
  6926. }
  6927. }
  6928. else if ( pChildToken -> GetType() == TYPE_METHOD )
  6929. {
  6930. Token *pArgToken;
  6931. // For each method arg check
  6932. // that type is VARIANT if a optional tag is specified
  6933. CTokenListWalker ArgListWalker ( pChildToken );
  6934. while ( pArgToken = ArgListWalker.GetNext() )
  6935. {
  6936. szAType = pArgToken->GetTagValue ( METHODARG_TYPE );
  6937. if ( pArgToken->IsSet ( METHODARG_OPTIONAL ) &&
  6938. !(szAType == "VARIANT" || szAType == "VARIANT*") )
  6939. {
  6940. // MIDL will let this through but you'd never be able to
  6941. // set the default
  6942. sprintf ( szErrorText, "Method arg type must be VARIANT with optional: tag on %s:%s\n",
  6943. (LPCSTR)pToken->GetTagValue ( NAME_TAG ),
  6944. (LPCSTR)pChildToken->GetTagValue ( METHOD_NAME ) );
  6945. ReportError ( szErrorText );
  6946. return FALSE;
  6947. }
  6948. if ( LookupType ( pArgToken -> GetTagValue ( METHODARG_TYPE ),
  6949. szHandler, szFnPrefix ) )
  6950. {
  6951. if (szHandler == "Enum" &&
  6952. !(pToken->GetType() == TYPE_INTERFACE &&
  6953. pToken->IsSet(INTERFACE_CUSTOM)))
  6954. {
  6955. sprintf ( szErrorText, "You must set type:BSTR for an enum %s Method:%s arg:%s\n",
  6956. (LPCSTR)pToken->GetTagValue ( NAME_TAG ),
  6957. (LPCSTR)pChildToken->GetTagValue ( METHOD_NAME ),
  6958. (LPCSTR)pArgToken->GetTagValue ( METHODARG_ARGNAME ) );
  6959. ReportError ( szErrorText );
  6960. return FALSE;
  6961. }
  6962. }
  6963. }
  6964. }
  6965. }
  6966. }
  6967. }
  6968. return TRUE;
  6969. }
  6970. //
  6971. // Patch up all interfaces which are not a primary default interfaces tearoff
  6972. // and mark as such (NOPRIMARY). Classes marked as NOPRIMARY will be derived
  6973. // from the inheritance chain instead of being derived from IDispatch.
  6974. //
  6975. BOOL
  6976. CPDLParser::PatchInterfaces ()
  6977. {
  6978. CTokenListWalker ThisFilesList(pRuntimeList, _pszPDLFileName);
  6979. Token *pClassToken;
  6980. Token *pInterf;
  6981. while (pClassToken = ThisFilesList.GetNext(TYPE_CLASS))
  6982. {
  6983. CString szInterface;
  6984. szInterface = pClassToken->GetTagValue(CLASS_INTERFACE);
  6985. if (!FindTearoff(pClassToken->GetTagValue(CLASS_NAME),
  6986. (LPCSTR)szInterface))
  6987. {
  6988. CString szInterfSuper;
  6989. pInterf = FindInterface(szInterface);
  6990. while (pInterf)
  6991. {
  6992. pInterf->Set(INTERFACE_NOPRIMARYTEAROFF);
  6993. szInterfSuper = pInterf->GetTagValue(INTERFACE_SUPER);
  6994. pInterf = FindInterface(szInterfSuper);
  6995. }
  6996. }
  6997. }
  6998. return TRUE;
  6999. }
  7000. const CCachedAttrArrayInfo*
  7001. CPDLParser::GetCachedAttrArrayInfo( LPCSTR szDispId )
  7002. {
  7003. CCachedAttrArrayInfo *pCCAAI = rgCachedAttrArrayInfo;
  7004. while (pCCAAI->szDispId)
  7005. {
  7006. if (0==strcmp(szDispId, pCCAAI->szDispId))
  7007. return pCCAAI;
  7008. ++pCCAAI;
  7009. }
  7010. //This is means it is not applied to a XF structure
  7011. return pCCAAI;
  7012. }
  7013. BOOL CPDLParser::GenerateHTMFile ()
  7014. {
  7015. Token *pToken;
  7016. CTokenListWalker WholeList ( pRuntimeList );
  7017. CTokenListWalker ThisFilesList ( pRuntimeList, _pszPDLFileName );
  7018. fprintf ( fpHTMFile, "<HTML>\n" );
  7019. fprintf ( fpHTMFile, "<HEAD>\n" );
  7020. fprintf ( fpHTMFile, "<TITLE>Interface Documentation from %s</TITLE>\n", _pszPDLFileName );
  7021. fprintf ( fpHTMFile, "</HEAD>\n" );
  7022. fprintf ( fpHTMFile, "<BODY>\n" );
  7023. fprintf ( fpHTMFile, "<P>\n" );
  7024. while ( pToken = ThisFilesList.GetNext ( TYPE_ENUM ) )
  7025. {
  7026. if ( !pToken -> IsSet ( ENUM_HIDDEN ))
  7027. {
  7028. fprintf ( fpHTMFile, "<B><U>Enumerations:</U></B> %s\n",
  7029. pToken->GetTagValue ( ENUM_NAME ) );
  7030. fprintf ( fpHTMFile, "<P>\n" );
  7031. fprintf ( fpHTMFile, "<TABLE WIDTH=70%%>\n" );
  7032. fprintf ( fpHTMFile, "<TR>\n" );
  7033. fprintf ( fpHTMFile, "<TH WIDTH=50%% ALIGN=\"Left\">Name</TH>\n" );
  7034. fprintf ( fpHTMFile, "<TH WIDTH=25%% ALIGN=\"Center\">String</TH>\n" );
  7035. fprintf ( fpHTMFile, "</TR>\n" );
  7036. GenerateEnumHTM ( pToken,
  7037. pToken -> IsSet ( ENUM_PREFIX ) ?
  7038. pToken->GetTagValue ( ENUM_PREFIX ) :
  7039. pToken->GetTagValue ( ENUM_NAME ) ); // sort enums
  7040. fprintf ( fpHTMFile, "</TABLE>\n" );
  7041. fprintf ( fpHTMFile, "<P>\n" );
  7042. }
  7043. }
  7044. // Output interface documentation
  7045. ThisFilesList.Reset();
  7046. while ( (pToken = ThisFilesList.GetNext ( TYPE_INTERFACE )) )
  7047. {
  7048. if (_stricmp("IUnknown", pToken->GetTagValue ( INTERFACE_NAME )) &&
  7049. _stricmp("IDispatch", pToken->GetTagValue ( INTERFACE_NAME )) )
  7050. {
  7051. char achFilePrefix[100];
  7052. strcpy (achFilePrefix, _pszPDLFileName);
  7053. char *pDot = strchr(achFilePrefix, '.');
  7054. if (pDot) {
  7055. *pDot = '\0';
  7056. }
  7057. else {
  7058. strcpy(achFilePrefix, "badpdl");
  7059. }
  7060. fprintf ( fpHTMIndexFile, "<A NAME=\"Index_Interface_%s\">Interface: <A HREF=\"%s.htm#Interface_%s\">%s</A><BR>\n",
  7061. pToken->GetTagValue ( INTERFACE_NAME ),
  7062. achFilePrefix, pToken->GetTagValue ( INTERFACE_NAME ),
  7063. pToken->GetTagValue ( INTERFACE_NAME ));
  7064. fprintf ( fpHTMFile, "<P>\n" );
  7065. fprintf ( fpHTMFile, "<A NAME=\"Interface_%s\">\n", pToken->GetTagValue ( INTERFACE_NAME ) );
  7066. fprintf ( fpHTMFile, "<TABLE>\n" );
  7067. fprintf ( fpHTMFile, "<TR><TD><H1>Interface</H1></TD>"
  7068. "<TR><TD><B>%s</B></TD><TD> GUID: </TD><TD>%s</TD></TR>"
  7069. "<TR><TD>inherits from interface</TD></TR>"
  7070. "<TR><TD><B><A HREF=\"AllIndex.htm#Index_Interface_%s\">%s</A></B></TD></TR>\n"
  7071. "</TABLE>\n",
  7072. pToken->GetTagValue ( INTERFACE_NAME ),
  7073. pToken->GetTagValue ( INTERFACE_GUID ),
  7074. pToken->GetTagValue ( INTERFACE_SUPER ),
  7075. pToken->GetTagValue ( INTERFACE_SUPER ) );
  7076. fprintf ( fpHTMFile, "<P>\n" );
  7077. fprintf ( fpHTMFile, "<HR>\n" );
  7078. fprintf ( fpHTMFile, "<H2>Properties</H2>\n" );
  7079. fprintf ( fpHTMFile, "<TABLE>\n" );
  7080. fprintf ( fpHTMFile, "<TR>" );
  7081. fprintf ( fpHTMFile, "<TH>Name</TH>" );
  7082. fprintf ( fpHTMFile, "<TH>AType</TH>" );
  7083. fprintf ( fpHTMFile, "<TH>DISPID</TH>" );
  7084. fprintf ( fpHTMFile, "<TH>G</TH>" );
  7085. fprintf ( fpHTMFile, "<TH>S</TH>" );
  7086. fprintf ( fpHTMFile, "<TH>DT</TH>" );
  7087. fprintf ( fpHTMFile, "<TH>Default</TH>" );
  7088. fprintf ( fpHTMFile, "<TH>Min</TH>" );
  7089. fprintf ( fpHTMFile, "<TH>Max</TH>" );
  7090. fprintf ( fpHTMFile, "</TR>\n" );
  7091. GenerateInterfacePropertiesHTM ( pToken ); // sort attributes
  7092. fprintf ( fpHTMFile, "</TABLE>" );
  7093. fprintf ( fpHTMFile, "<H2>Methods</H2>\n" );
  7094. fprintf ( fpHTMFile, "<TABLE BORDER=1>\n" );
  7095. fprintf ( fpHTMFile, "<TR>" );
  7096. fprintf ( fpHTMFile, "<TH>Ret. Name</TH>" );
  7097. fprintf ( fpHTMFile, "<TH>Name</TH>" );
  7098. fprintf ( fpHTMFile, "<TH>Param Dir</TH>" );
  7099. fprintf ( fpHTMFile, "<TH>Param Type</TH>" );
  7100. fprintf ( fpHTMFile, "<TH>Param Name</TH>" );
  7101. fprintf ( fpHTMFile, "<TH>Default Value</TH>" );
  7102. fprintf ( fpHTMFile, "<TH>Optional</TH>" );
  7103. fprintf ( fpHTMFile, "<TH>Ret. Type</TH>" );
  7104. fprintf ( fpHTMFile, "</TR>\n" );
  7105. GenerateInterfaceMethodHTM ( pToken ); // sort attributes
  7106. fprintf ( fpHTMFile, "</TABLE>" );
  7107. }
  7108. }
  7109. // Output eventset documentation
  7110. ThisFilesList.Reset();
  7111. while ( (pToken = ThisFilesList.GetNext ( TYPE_EVENT )) )
  7112. {
  7113. if (_stricmp("IDispatch", pToken->GetTagValue ( INTERFACE_NAME )) )
  7114. {
  7115. char achFilePrefix[100];
  7116. strcpy (achFilePrefix, _pszPDLFileName);
  7117. char *pDot = strchr(achFilePrefix, '.');
  7118. if (pDot) {
  7119. *pDot = '\0';
  7120. }
  7121. else {
  7122. strcpy(achFilePrefix, "badpdl");
  7123. }
  7124. fprintf ( fpHTMIndexFile, "<A NAME=\"Index_Eventset_%s\">Eventset: <A HREF=\"%s.htm#Eventset_%s\">%s</A><BR>\n",
  7125. pToken->GetTagValue ( EVENT_NAME ),
  7126. achFilePrefix, pToken->GetTagValue ( EVENT_NAME ),
  7127. pToken->GetTagValue ( EVENT_NAME ));
  7128. fprintf ( fpHTMFile, "<BR><BR>\n" );
  7129. fprintf ( fpHTMFile, "<A NAME=\"Eventset_%s\">\n", pToken->GetTagValue ( EVENT_NAME ) );
  7130. fprintf ( fpHTMFile, "<TABLE>\n" );
  7131. fprintf ( fpHTMFile, "<TR><TD><H1>Event Set</H1></TD>"
  7132. "<TR><TD><B>%s</B></TD><TD> GUID: </TD><TD>%s</TD></TR>"
  7133. "<TR><TD>inherits from event set</TD></TR>"
  7134. "<TR><TD><B><A HREF=\"AllIndex.htm#Index_Eventset_%s\">%s</A></B></TD></TR>\n"
  7135. "</TABLE>\n",
  7136. pToken->GetTagValue ( EVENT_NAME ),
  7137. pToken->GetTagValue ( EVENT_GUID ),
  7138. pToken->GetTagValue ( EVENT_SUPER ),
  7139. pToken->GetTagValue ( EVENT_SUPER ) );
  7140. fprintf ( fpHTMFile, "<HR>\n" );
  7141. fprintf ( fpHTMFile, "<H2>Methods</H2>\n" );
  7142. fprintf ( fpHTMFile, "<TABLE BORDER=1>\n" );
  7143. fprintf ( fpHTMFile, "<TR>" );
  7144. fprintf ( fpHTMFile, "<TH>Ret. Name</TH>" );
  7145. fprintf ( fpHTMFile, "<TH>Name</TH>" );
  7146. fprintf ( fpHTMFile, "<TH>DISPID</TH>" );
  7147. fprintf ( fpHTMFile, "<TH>Cancelable</TH>" );
  7148. fprintf ( fpHTMFile, "<TH>Bubbling</TH>" );
  7149. fprintf ( fpHTMFile, "<TH>Param Dir</TH>" );
  7150. fprintf ( fpHTMFile, "<TH>Param Type</TH>" );
  7151. fprintf ( fpHTMFile, "<TH>Param Name</TH>" );
  7152. fprintf ( fpHTMFile, "<TH>Default Value</TH>" );
  7153. fprintf ( fpHTMFile, "<TH>Optional</TH>" );
  7154. fprintf ( fpHTMFile, "<TH>Ret. Type</TH>" );
  7155. fprintf ( fpHTMFile, "</TR>\n" );
  7156. GenerateEventMethodHTM ( pToken ); // sort attributes
  7157. fprintf ( fpHTMFile, "</TABLE>" );
  7158. }
  7159. }
  7160. fprintf ( fpHTMFile, "</BODY>\n");
  7161. fprintf ( fpHTMFile, "</HTML>\n");
  7162. return TRUE;
  7163. }
  7164. void CPDLParser::GenerateArg ( Token *pArgToken )
  7165. {
  7166. if ( ! pArgToken -> IsSet ( METHODARG_RETURNVALUE ) )
  7167. {
  7168. fprintf ( fpHTMFile, "&nbsp[%s] %s %s",
  7169. pArgToken -> IsSet ( METHODARG_OUT ) ? "out" : "in",
  7170. pArgToken -> GetTagValue ( METHODARG_TYPE ),
  7171. pArgToken -> GetTagValue ( METHODARG_ARGNAME ) );
  7172. if ( pArgToken -> IsSet ( METHODARG_DEFAULTVALUE ) )
  7173. {
  7174. fprintf ( fpHTMFile, "=%s",
  7175. pArgToken -> GetTagValue ( METHODARG_DEFAULTVALUE ) );
  7176. }
  7177. if ( pArgToken -> IsSet ( METHODARG_OPTIONAL ) )
  7178. {
  7179. fprintf ( fpHTMFile, " [optional]" );
  7180. }
  7181. }
  7182. }
  7183. void CPDLParser::GenerateInterfaceArg ( Token *pArgToken )
  7184. {
  7185. if ( ! pArgToken -> IsSet ( METHODARG_RETURNVALUE ) )
  7186. {
  7187. fprintf ( fpHTMFile, "<TD>%s</TD><TD>%s</TD><TD>%s</TD>",
  7188. pArgToken -> IsSet ( METHODARG_OUT ) ? "out" : "in",
  7189. pArgToken -> GetTagValue ( METHODARG_TYPE ),
  7190. pArgToken -> GetTagValue ( METHODARG_ARGNAME ) );
  7191. fprintf ( fpHTMFile, "<TD>%s</TD><TD>%s</TD>",
  7192. pArgToken -> IsSet ( METHODARG_DEFAULTVALUE ) ?
  7193. (pArgToken -> GetTagValue ( METHODARG_DEFAULTVALUE )) : "",
  7194. pArgToken -> IsSet ( METHODARG_OPTIONAL) ?
  7195. "Y" : "N" );
  7196. }
  7197. }
  7198. void CPDLParser::GenerateMethodHTM ( Token *pIntfToken )
  7199. {
  7200. CTokenListWalker *pChildList;
  7201. Token *pChildToken;
  7202. Token *pArgToken;
  7203. int cArgs;
  7204. CString szSuper;
  7205. CTokenListWalker *ptlw = NULL;
  7206. pChildList = new CTokenListWalker ( pIntfToken );
  7207. szSuper = pIntfToken->GetTagValue ( INTERFACE_SUPER );
  7208. do
  7209. {
  7210. while ( pChildToken = pChildList -> GetNext() )
  7211. {
  7212. CString szRetValArg;
  7213. CString szRetValType;
  7214. CTokenListWalker ArgListWalker ( pChildToken );
  7215. cArgs = 0;
  7216. // Loop thru all arguments.
  7217. while ( (pArgToken = ArgListWalker.GetNext()) != NULL &&
  7218. pArgToken -> GetType () == TYPE_METHOD_ARG )
  7219. {
  7220. // Looking for a return value.
  7221. if ( pArgToken -> IsSet ( METHODARG_RETURNVALUE ) )
  7222. {
  7223. // If a return value exist then get the argument name.
  7224. szRetValArg = pArgToken -> GetTagValue (
  7225. pArgToken -> IsSet ( METHODARG_ARGNAME ) ?
  7226. METHODARG_ARGNAME : METHODARG_RETURNVALUE );
  7227. szRetValType = pArgToken -> GetTagValue ( METHODARG_TYPE );
  7228. }
  7229. else
  7230. {
  7231. cArgs++;
  7232. }
  7233. }
  7234. if ( strlen ( szRetValArg ) )
  7235. {
  7236. fprintf ( fpHTMFile, "<TR><TD>%s = <I>object.</I><B>%s</B>",
  7237. (LPCSTR)szRetValArg,
  7238. pChildToken -> GetTagValue ( METHOD_NAME ) );
  7239. }
  7240. else
  7241. {
  7242. fprintf ( fpHTMFile, "<TR><TD><I>object.</I><B>%s</B>",
  7243. pChildToken -> GetTagValue ( METHOD_NAME ) );
  7244. }
  7245. int cArgIndex = 0;
  7246. ArgListWalker.Reset ( );
  7247. while ( ( pArgToken = ArgListWalker.GetNext ( ) ) != NULL &&
  7248. pArgToken -> GetType () == TYPE_METHOD_ARG )
  7249. {
  7250. if ( ! pArgToken -> IsSet ( METHODARG_RETURNVALUE ) )
  7251. {
  7252. if (cArgIndex == 0)
  7253. {
  7254. switch (cArgs)
  7255. {
  7256. case 0:
  7257. fprintf ( fpHTMFile, "<TD>( )</TD>\n" );
  7258. fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
  7259. (LPCSTR)szRetValType );
  7260. fprintf ( fpHTMFile, "</TR>\n" );
  7261. break;
  7262. case 1:
  7263. fprintf ( fpHTMFile, "<TD>(" );
  7264. GenerateArg( pArgToken );
  7265. fprintf ( fpHTMFile, "&nbsp)</TD>\n" );
  7266. fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
  7267. (LPCSTR)szRetValType );
  7268. fprintf ( fpHTMFile, "</TR>\n" );
  7269. break;
  7270. default:
  7271. fprintf ( fpHTMFile, "<TD>(" );
  7272. GenerateArg( pArgToken );
  7273. fprintf ( fpHTMFile, ",</TD>\n" );
  7274. fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
  7275. (LPCSTR)szRetValType );
  7276. fprintf ( fpHTMFile, "</TR>\n" );
  7277. break;
  7278. }
  7279. }
  7280. else
  7281. {
  7282. if (cArgIndex > 1)
  7283. {
  7284. fprintf ( fpHTMFile, ",</TD></TR>\n" );
  7285. }
  7286. fprintf ( fpHTMFile, "<TR><TD></TD><TD>&nbsp" );
  7287. GenerateArg( pArgToken );
  7288. }
  7289. cArgIndex++;
  7290. }
  7291. }
  7292. if ( cArgIndex == 0 )
  7293. {
  7294. fprintf ( fpHTMFile, "<TD>( )</TD>\n" );
  7295. fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
  7296. (LPCSTR)szRetValType );
  7297. fprintf ( fpHTMFile, "</TR>\n" );
  7298. }
  7299. else if ( cArgIndex > 1 )
  7300. {
  7301. fprintf ( fpHTMFile, ")</TD></TR>\n" );
  7302. }
  7303. fprintf ( fpHTMFile, "<TR>&nbsp</TR>" );
  7304. }
  7305. // Get inherited interface.
  7306. if ( strlen ( szSuper ) )
  7307. {
  7308. if (ptlw == NULL)
  7309. {
  7310. ptlw = new CTokenListWalker ( pRuntimeList, _pszPDLFileName );
  7311. }
  7312. else
  7313. {
  7314. ptlw->Reset();
  7315. }
  7316. TryAgain:
  7317. pIntfToken = ptlw->GetNext ( TYPE_INTERFACE, szSuper );
  7318. if (pIntfToken)
  7319. {
  7320. szSuper = pIntfToken->GetTagValue ( INTERFACE_SUPER );
  7321. delete pChildList;
  7322. pChildList = new CTokenListWalker ( pIntfToken );
  7323. }
  7324. else
  7325. {
  7326. if ( !ptlw->IsGenericWalker ( ) )
  7327. {
  7328. delete ptlw;
  7329. ptlw = new CTokenListWalker ( pRuntimeList );
  7330. goto TryAgain;
  7331. }
  7332. }
  7333. }
  7334. else
  7335. {
  7336. break;
  7337. }
  7338. } while (pIntfToken);
  7339. delete pChildList;
  7340. delete ptlw;
  7341. }
  7342. void CPDLParser::GenerateInterfaceMethodHTM ( Token *pIntfToken )
  7343. {
  7344. CTokenListWalker *pChildList;
  7345. Token *pChildToken;
  7346. Token *pArgToken;
  7347. int cArgs;
  7348. CString szSuper;
  7349. pChildList = new CTokenListWalker ( pIntfToken );
  7350. szSuper = pIntfToken->GetTagValue ( INTERFACE_SUPER );
  7351. while ( pChildToken = pChildList -> GetNext() )
  7352. {
  7353. CString szRetValArg;
  7354. CString szRetValType;
  7355. CTokenListWalker ArgListWalker ( pChildToken );
  7356. cArgs = 0;
  7357. // Loop thru all arguments.
  7358. while ( (pArgToken = ArgListWalker.GetNext()) != NULL &&
  7359. pArgToken -> GetType () == TYPE_METHOD_ARG )
  7360. {
  7361. // Looking for a return value.
  7362. if ( pArgToken -> IsSet ( METHODARG_RETURNVALUE ) )
  7363. {
  7364. // If a return value exist then get the argument name.
  7365. szRetValArg = pArgToken -> GetTagValue (
  7366. pArgToken -> IsSet ( METHODARG_ARGNAME ) ?
  7367. METHODARG_ARGNAME : METHODARG_RETURNVALUE );
  7368. szRetValType = pArgToken -> GetTagValue ( METHODARG_TYPE );
  7369. }
  7370. else
  7371. {
  7372. cArgs++;
  7373. }
  7374. }
  7375. if ( strlen ( szRetValArg ) )
  7376. {
  7377. fprintf ( fpHTMFile, "<TR><TD>%s</TD><TD><I>object.</I><B>%s</B></TD>",
  7378. (LPCSTR)szRetValArg,
  7379. pChildToken -> GetTagValue ( METHOD_NAME ) );
  7380. }
  7381. else
  7382. {
  7383. fprintf ( fpHTMFile, "<TR><TD></TD><TD><I>object.</I><B>%s</B></TD>",
  7384. pChildToken -> GetTagValue ( METHOD_NAME ) );
  7385. }
  7386. int cArgIndex = 0;
  7387. ArgListWalker.Reset ( );
  7388. while ( ( pArgToken = ArgListWalker.GetNext ( ) ) != NULL &&
  7389. pArgToken -> GetType () == TYPE_METHOD_ARG )
  7390. {
  7391. if ( ! pArgToken -> IsSet ( METHODARG_RETURNVALUE ) )
  7392. {
  7393. if (cArgIndex == 0)
  7394. {
  7395. switch (cArgs)
  7396. {
  7397. case 0:
  7398. fprintf ( fpHTMFile, "<TD></TD><TD></TD><TD></TD><TD></TD><TD></TD> <!-- 1 -->" );
  7399. fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
  7400. (LPCSTR)szRetValType );
  7401. fprintf ( fpHTMFile, "</TR>\n" );
  7402. break;
  7403. default:
  7404. GenerateInterfaceArg( pArgToken );
  7405. fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
  7406. (LPCSTR)szRetValType );
  7407. fprintf ( fpHTMFile, "</TR>\n" );
  7408. break;
  7409. }
  7410. }
  7411. else
  7412. {
  7413. if (cArgIndex > 1)
  7414. {
  7415. fprintf ( fpHTMFile, "</TR> <!-- Hello -->\n" );
  7416. }
  7417. fprintf ( fpHTMFile, "<TR><TD></TD><TD></TD>" );
  7418. GenerateInterfaceArg( pArgToken );
  7419. }
  7420. cArgIndex++;
  7421. }
  7422. }
  7423. if ( cArgIndex == 0 )
  7424. {
  7425. fprintf ( fpHTMFile, "<TD></TD><TD></TD><TD></TD><TD></TD><TD></TD> <!-- 2 -->" );
  7426. fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
  7427. (LPCSTR)szRetValType );
  7428. fprintf ( fpHTMFile, "</TR>\n" );
  7429. }
  7430. else if ( cArgIndex > 1 )
  7431. {
  7432. fprintf ( fpHTMFile, "</TR> <!-- 3 -->\n" );
  7433. }
  7434. fprintf ( fpHTMFile, "<TR></TR>" );
  7435. }
  7436. delete pChildList;
  7437. }
  7438. void CPDLParser::GenerateEventMethodHTM ( Token *pIntfToken )
  7439. {
  7440. CTokenListWalker *pChildList;
  7441. Token *pChildToken;
  7442. Token *pArgToken;
  7443. int cArgs;
  7444. CString szSuper;
  7445. pChildList = new CTokenListWalker ( pIntfToken );
  7446. szSuper = pIntfToken->GetTagValue ( INTERFACE_SUPER );
  7447. while ( pChildToken = pChildList -> GetNext() )
  7448. {
  7449. CString szRetValArg;
  7450. CString szRetValType;
  7451. CTokenListWalker ArgListWalker ( pChildToken );
  7452. cArgs = 0;
  7453. // Loop thru all arguments.
  7454. while ( (pArgToken = ArgListWalker.GetNext()) != NULL &&
  7455. pArgToken -> GetType () == TYPE_METHOD_ARG )
  7456. {
  7457. // Looking for a return value.
  7458. if ( pArgToken -> IsSet ( METHODARG_RETURNVALUE ) )
  7459. {
  7460. // If a return value exist then get the argument name.
  7461. szRetValArg = pArgToken -> GetTagValue (
  7462. pArgToken -> IsSet ( METHODARG_ARGNAME ) ?
  7463. METHODARG_ARGNAME : METHODARG_RETURNVALUE );
  7464. szRetValType = pArgToken -> GetTagValue ( METHODARG_TYPE );
  7465. }
  7466. else
  7467. {
  7468. cArgs++;
  7469. }
  7470. }
  7471. if ( strlen ( szRetValArg ) )
  7472. {
  7473. fprintf ( fpHTMFile, "<TR><TD>%s</TD><TD><I>object.</I><B>%s</B></TD>",
  7474. (LPCSTR)szRetValArg,
  7475. pChildToken -> GetTagValue ( METHOD_NAME ) );
  7476. }
  7477. else
  7478. {
  7479. fprintf ( fpHTMFile, "<TR><TD></TD><TD><I>object.</I><B>%s</B></TD>",
  7480. pChildToken -> GetTagValue ( METHOD_NAME ) );
  7481. }
  7482. fprintf ( fpHTMFile, "<TD>%s</TD><TD>%s</TD><TD>%s</TD>",
  7483. pChildToken->IsSet(METHOD_DISPID) ? pChildToken->GetTagValue ( METHOD_DISPID ) : "",
  7484. pChildToken->IsSet(METHOD_CANCELABLE) ? "Y" : "N",
  7485. pChildToken->IsSet(METHOD_BUBBLING) ? "Y" : "N" );
  7486. int cArgIndex = 0;
  7487. ArgListWalker.Reset ( );
  7488. while ( ( pArgToken = ArgListWalker.GetNext ( ) ) != NULL &&
  7489. pArgToken -> GetType () == TYPE_METHOD_ARG )
  7490. {
  7491. if ( ! pArgToken -> IsSet ( METHODARG_RETURNVALUE ) )
  7492. {
  7493. if (cArgIndex == 0)
  7494. {
  7495. switch (cArgs)
  7496. {
  7497. case 0:
  7498. fprintf ( fpHTMFile, "<TD></TD><TD></TD><TD></TD><TD></TD><TD></TD> <!-- 1 -->" );
  7499. fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
  7500. (LPCSTR)szRetValType );
  7501. fprintf ( fpHTMFile, "</TR>\n" );
  7502. break;
  7503. default:
  7504. GenerateInterfaceArg( pArgToken );
  7505. fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
  7506. (LPCSTR)szRetValType );
  7507. fprintf ( fpHTMFile, "</TR>\n" );
  7508. break;
  7509. }
  7510. }
  7511. else
  7512. {
  7513. if (cArgIndex > 1)
  7514. {
  7515. fprintf ( fpHTMFile, "</TR> <!-- Hello -->\n" );
  7516. }
  7517. fprintf ( fpHTMFile, "<TR><TD></TD><TD></TD><TD></TD><TD></TD><TD></TD>" );
  7518. GenerateInterfaceArg( pArgToken );
  7519. }
  7520. cArgIndex++;
  7521. }
  7522. }
  7523. if ( cArgIndex == 0 )
  7524. {
  7525. fprintf ( fpHTMFile, "<TD></TD><TD></TD><TD></TD><TD></TD><TD></TD> <!-- 2 -->" );
  7526. fprintf ( fpHTMFile, "<TD ALIGN=\"Center\">%s</TD>\n",
  7527. (LPCSTR)szRetValType );
  7528. fprintf ( fpHTMFile, "</TR>\n" );
  7529. }
  7530. else if ( cArgIndex > 1 )
  7531. {
  7532. fprintf ( fpHTMFile, "</TR> <!-- 3 -->\n" );
  7533. }
  7534. fprintf ( fpHTMFile, "<TR></TR>" );
  7535. }
  7536. delete pChildList;
  7537. }
  7538. void CPDLParser::GenerateEnumHTM ( Token *pClassToken, char *pEnumPrefix )
  7539. {
  7540. CTokenListWalker ChildList ( pClassToken );
  7541. Token *pChildToken;
  7542. CString szStringValue;
  7543. while ( pChildToken = ChildList.GetNext() )
  7544. {
  7545. if ( pChildToken -> GetType() == TYPE_EVAL )
  7546. {
  7547. fprintf ( fpHTMFile, "<TR>\n<TD>%s%s</TD><TD ALIGN=\"Center\">\"%s\"</TD>",
  7548. pEnumPrefix,
  7549. pChildToken -> GetTagValue ( EVAL_NAME ),
  7550. pChildToken -> IsSet ( EVAL_STRING ) ?
  7551. pChildToken -> GetTagValue ( EVAL_STRING ) :
  7552. pChildToken -> GetTagValue ( EVAL_NAME ) );
  7553. fprintf ( fpHTMFile, "</TR>\n");
  7554. }
  7555. }
  7556. }
  7557. void CPDLParser::GeneratePropertiesHTM ( Token *pIntfToken, BOOL fAttributes )
  7558. {
  7559. CTokenListWalker *pChildList;
  7560. Token *pChildToken;
  7561. CString szSuper;
  7562. CTokenListWalker *ptlw = NULL;
  7563. pChildList = new CTokenListWalker ( pIntfToken );
  7564. szSuper = pIntfToken->GetTagValue ( INTERFACE_SUPER );
  7565. do
  7566. {
  7567. while ( pChildToken = pChildList->GetNext() )
  7568. {
  7569. // Attributes are only properties which are not abstract and the
  7570. // ppflags is not PROPPARAM_NOTHTML.
  7571. if ( pChildToken -> GetType () == TYPE_PROPERTY &&
  7572. fAttributes == (
  7573. !pChildToken -> IsSet ( PROPERTY_ABSTRACT ) &&
  7574. pChildToken -> IsSet ( PROPERTY_NOPERSIST ) ) )
  7575. {
  7576. if (fAttributes)
  7577. {
  7578. fprintf ( fpHTMFile, "<TR><TD>%s</TD><TD>%s</TD><TD>%s</TD>",
  7579. pChildToken -> GetTagValue (
  7580. pChildToken -> IsSet ( PROPERTY_SZATTRIBUTE ) ?
  7581. PROPERTY_SZATTRIBUTE : PROPERTY_NAME ),
  7582. pChildToken -> GetTagValue ( PROPERTY_NAME ),
  7583. pChildToken -> GetTagValue ( PROPERTY_ATYPE ) );
  7584. }
  7585. else
  7586. {
  7587. fprintf ( fpHTMFile, "<TR><TD>%s</TD><TD>%s</TD>",
  7588. pChildToken -> GetTagValue ( PROPERTY_NAME ),
  7589. pChildToken -> GetTagValue ( PROPERTY_ATYPE ) );
  7590. }
  7591. fprintf ( fpHTMFile, "<TD>%s</TD>",
  7592. pChildToken -> IsSet ( PROPERTY_NOTPRESENTDEFAULT ) ?
  7593. pChildToken -> GetTagValue ( PROPERTY_NOTPRESENTDEFAULT ) :
  7594. "" );
  7595. fprintf ( fpHTMFile, "<TD>%s</TD>",
  7596. pChildToken -> IsSet ( PROPERTY_MIN ) ?
  7597. pChildToken -> GetTagValue ( PROPERTY_MIN ) :
  7598. "" );
  7599. fprintf ( fpHTMFile, "<TD>%s</TD>",
  7600. pChildToken -> IsSet ( PROPERTY_MAX ) ?
  7601. pChildToken -> GetTagValue ( PROPERTY_MAX ) :
  7602. "" );
  7603. if ( pChildToken -> IsSet ( PROPERTY_SET ) &&
  7604. pChildToken -> IsSet ( PROPERTY_GET ) )
  7605. {
  7606. fprintf ( fpHTMFile, "<TD>R/W</TD>" );
  7607. }
  7608. else if ( pChildToken -> IsSet ( PROPERTY_GET ) )
  7609. {
  7610. fprintf ( fpHTMFile, "<TD>R/O</TD>" );
  7611. }
  7612. else
  7613. {
  7614. fprintf ( fpHTMFile, "<TD>W/O</TD>" );
  7615. }
  7616. fprintf ( fpHTMFile,
  7617. pChildToken -> IsSet ( PROPERTY_SETDESIGNMODE ) ?
  7618. "<TD>R/W</TD>" : "<TD>R/O</TD>" );
  7619. fprintf ( fpHTMFile, "</TR>\n" );
  7620. }
  7621. }
  7622. // Get inherited interface.
  7623. if ( strlen ( szSuper ) )
  7624. {
  7625. if (ptlw == NULL)
  7626. {
  7627. ptlw = new CTokenListWalker ( pRuntimeList, _pszPDLFileName );
  7628. }
  7629. else
  7630. {
  7631. ptlw->Reset();
  7632. }
  7633. TryAgain:
  7634. pIntfToken = ptlw->GetNext ( TYPE_INTERFACE, szSuper );
  7635. if (pIntfToken)
  7636. {
  7637. szSuper = pIntfToken->GetTagValue ( INTERFACE_SUPER );
  7638. delete pChildList;
  7639. pChildList = new CTokenListWalker ( pIntfToken );
  7640. }
  7641. else
  7642. {
  7643. if ( !ptlw->IsGenericWalker ( ) )
  7644. {
  7645. delete ptlw;
  7646. ptlw = new CTokenListWalker ( pRuntimeList );
  7647. goto TryAgain;
  7648. }
  7649. }
  7650. }
  7651. else
  7652. {
  7653. break;
  7654. }
  7655. } while (pIntfToken);
  7656. delete pChildList;
  7657. delete ptlw;
  7658. }
  7659. #define GET_TAG_VALUE(pToken, value) (pToken->IsSet(value) ? pToken->GetTagValue(value) : "")
  7660. void CPDLParser::GenerateInterfacePropertiesHTM ( Token *pIntfToken )
  7661. {
  7662. CTokenListWalker *pChildList;
  7663. Token *pChildToken;
  7664. CString szSuper;
  7665. pChildList = new CTokenListWalker ( pIntfToken );
  7666. szSuper = pIntfToken->GetTagValue ( INTERFACE_SUPER );
  7667. while ( pChildToken = pChildList->GetNext() )
  7668. {
  7669. if ( pChildToken -> GetType () == TYPE_PROPERTY )
  7670. {
  7671. fprintf ( fpHTMFile, "<TR>" );
  7672. fprintf ( fpHTMFile, "<TD>%s</TD>", GET_TAG_VALUE(pChildToken, PROPERTY_NAME) );
  7673. fprintf ( fpHTMFile, "<TD>%s</TD>", GET_TAG_VALUE(pChildToken, PROPERTY_ATYPE) );
  7674. fprintf ( fpHTMFile, "<TD>%s</TD>", GET_TAG_VALUE(pChildToken, PROPERTY_DISPID) );
  7675. fprintf ( fpHTMFile, "<TD>%s</TD>", pChildToken->IsSet(PROPERTY_GET) ? "Y" : "N" );
  7676. fprintf ( fpHTMFile, "<TD>%s</TD>", pChildToken->IsSet(PROPERTY_SET) ? "Y" : "N" );
  7677. fprintf ( fpHTMFile, "<TD>%s</TD>", pChildToken->IsSet(PROPERTY_SETDESIGNMODE) ? "Y" : "N" );
  7678. fprintf ( fpHTMFile, "<TD>%s</TD>", pChildToken->IsSet(PROPERTY_NOTPRESENTDEFAULT) ? pChildToken->GetTagValue(PROPERTY_NOTPRESENTDEFAULT) : "" );
  7679. fprintf ( fpHTMFile, "<TD>%s</TD>", pChildToken->IsSet(PROPERTY_MIN) ? pChildToken->GetTagValue(PROPERTY_MIN) : "" );
  7680. fprintf ( fpHTMFile, "<TD>%s</TD>", pChildToken->IsSet(PROPERTY_MAX) ? pChildToken->GetTagValue(PROPERTY_MAX) : "" );
  7681. fprintf ( fpHTMFile, "</TR>\n" );
  7682. }
  7683. }
  7684. delete pChildList;
  7685. }
  7686. #undef GET_TAG_VALUE
  7687. Token* CPDLParser::FindInterface (CString szInterfaceMatch)
  7688. {
  7689. CTokenListWalker WholeTree ( pRuntimeList );
  7690. Token *pInterfaceToken;
  7691. WholeTree.Reset();
  7692. while ( pInterfaceToken = WholeTree.GetNext ( TYPE_INTERFACE ) )
  7693. {
  7694. CString szInterface;
  7695. if ( !pInterfaceToken -> IsSet ( INTERFACE_ABSTRACT ) &&
  7696. pInterfaceToken -> IsSet ( INTERFACE_GUID ) )
  7697. {
  7698. szInterface = pInterfaceToken -> GetTagValue ( INTERFACE_NAME );
  7699. if (szInterface == szInterfaceMatch)
  7700. {
  7701. return pInterfaceToken;
  7702. }
  7703. }
  7704. }
  7705. return NULL;
  7706. }
  7707. // Only interfaces defined in this file.
  7708. Token* CPDLParser::FindInterfaceLocally (CString szInterfaceMatch)
  7709. {
  7710. CTokenListWalker TokenList ( pRuntimeList, _pszPDLFileName );
  7711. Token *pInterfaceToken;
  7712. TokenList.Reset();
  7713. while ( pInterfaceToken = TokenList.GetNext ( TYPE_INTERFACE ) )
  7714. {
  7715. CString szInterface;
  7716. if ( !pInterfaceToken -> IsSet ( INTERFACE_ABSTRACT ) &&
  7717. pInterfaceToken -> IsSet ( INTERFACE_GUID ) )
  7718. {
  7719. szInterface = pInterfaceToken -> GetTagValue ( INTERFACE_NAME );
  7720. if (szInterface == szInterfaceMatch)
  7721. {
  7722. return pInterfaceToken;
  7723. }
  7724. }
  7725. }
  7726. return NULL;
  7727. }
  7728. BOOL CPDLParser::IsPrimaryInterface(CString szInterface)
  7729. {
  7730. CTokenListWalker TokenList ( pRuntimeList, _pszPDLFileName );
  7731. Token *pClassToken;
  7732. TokenList.Reset();
  7733. while ( pClassToken = TokenList.GetNext ( TYPE_CLASS ) )
  7734. {
  7735. if (!_stricmp((LPSTR)pClassToken->GetTagValue(CLASS_INTERFACE),
  7736. szInterface))
  7737. return TRUE;
  7738. }
  7739. return FALSE;
  7740. }
  7741. Token* CPDLParser::FindClass (CString szClassMatch)
  7742. {
  7743. CTokenListWalker WholeTree ( pRuntimeList );
  7744. Token *pClassToken;
  7745. WholeTree.Reset();
  7746. while ( pClassToken = WholeTree.GetNext ( TYPE_CLASS ) )
  7747. {
  7748. CString szClass;
  7749. szClass = pClassToken -> GetTagValue ( CLASS_NAME );
  7750. if (szClass == szClassMatch)
  7751. {
  7752. return pClassToken;
  7753. }
  7754. }
  7755. return NULL;
  7756. }
  7757. Token * CPDLParser::IsSuperInterface( CString szSuper, Token * pInterface )
  7758. {
  7759. Token *pInterfaceToken;
  7760. CString szInterface;
  7761. if(!pInterface)
  7762. return NULL;
  7763. szInterface = pInterface->GetTagValue(INTERFACE_NAME);
  7764. pInterfaceToken = pInterface;
  7765. while ( pInterfaceToken )
  7766. {
  7767. if (szSuper == szInterface)
  7768. return pInterfaceToken;
  7769. szInterface = pInterfaceToken->GetTagValue(INTERFACE_SUPER);
  7770. pInterfaceToken = FindInterface(szInterface);
  7771. }
  7772. return NULL;
  7773. }
  7774. Token *
  7775. CPDLParser::FindMatchingEntryWOPropDesc(Token *pClass, Token *pToFindToken, BOOL fNameMatchOnly)
  7776. {
  7777. CTokenListWalker ChildWalker(pClass);
  7778. Token *pChildToken;
  7779. CString szInterface;
  7780. Token *pInterfToken;
  7781. Token *pFuncToken = NULL;
  7782. while (pChildToken = ChildWalker.GetNext())
  7783. {
  7784. if (pChildToken->GetType() == TYPE_IMPLEMENTS)
  7785. {
  7786. szInterface = pChildToken->GetTagValue(IMPLEMENTS_NAME);
  7787. pInterfToken = FindInterface(szInterface);
  7788. if (pInterfToken)
  7789. {
  7790. pFuncToken = FindMethodInInterfaceWOPropDesc(pInterfToken, pToFindToken, fNameMatchOnly);
  7791. if (pFuncToken)
  7792. break; // Found a match...
  7793. }
  7794. }
  7795. }
  7796. return pFuncToken;
  7797. }
  7798. Token*
  7799. CPDLParser::FindMethodInInterfaceWOPropDesc(Token *pInterface, Token *pToFindToken, BOOL fNameMatchOnly)
  7800. {
  7801. CTokenListWalker ChildList(pInterface);
  7802. Token *pChildToken = NULL;
  7803. while (pChildToken = ChildList.GetNext())
  7804. {
  7805. if (pChildToken->GetType() == pToFindToken->GetType())
  7806. {
  7807. if (pChildToken->GetType() == TYPE_METHOD && !pChildToken->IsSet(METHOD_NOPROPDESC))
  7808. {
  7809. CString szMethodName;
  7810. if (pToFindToken->IsSet(METHOD_NOPROPDESC) &&
  7811. pToFindToken->IsSet(METHOD_SZINTERFACEEXPOSE))
  7812. {
  7813. szMethodName = pToFindToken->GetTagValue(METHOD_SZINTERFACEEXPOSE);
  7814. }
  7815. else
  7816. {
  7817. szMethodName = pToFindToken->GetTagValue(METHOD_NAME);
  7818. }
  7819. if (!strcmp((LPCSTR)szMethodName,
  7820. (LPCSTR)pChildToken->GetTagValue(METHOD_NAME)))
  7821. {
  7822. CString szTypesSig;
  7823. CString szArgsType;
  7824. CString szFindTypesSig;
  7825. CString szFindArgsType;
  7826. BOOL fIgnore;
  7827. int cIgnore;
  7828. // If we only need a name match then we're done.
  7829. if (fNameMatchOnly)
  7830. break;
  7831. if (!BuildMethodSignature(pChildToken,
  7832. szTypesSig,
  7833. szArgsType,
  7834. fIgnore,
  7835. fIgnore,
  7836. cIgnore,
  7837. cIgnore))
  7838. return NULL;
  7839. if (!BuildMethodSignature(pToFindToken,
  7840. szFindTypesSig,
  7841. szFindArgsType,
  7842. fIgnore,
  7843. fIgnore,
  7844. cIgnore,
  7845. cIgnore))
  7846. return NULL;
  7847. // Exact signature match then use it.
  7848. if (!strcmp(szTypesSig, szFindTypesSig) &&
  7849. !strcmp(szArgsType, szFindArgsType))
  7850. break;
  7851. }
  7852. }
  7853. else if (pChildToken->GetType() == TYPE_PROPERTY && !pChildToken->IsSet(PROPERTY_NOPROPDESC))
  7854. {
  7855. CString szPropertyName;
  7856. if (pToFindToken->IsSet(PROPERTY_NOPROPDESC) &&
  7857. pToFindToken->IsSet(PROPERTY_SZINTERFACEEXPOSE))
  7858. {
  7859. szPropertyName = pToFindToken->GetTagValue(PROPERTY_SZINTERFACEEXPOSE);
  7860. }
  7861. else
  7862. {
  7863. szPropertyName = pToFindToken->GetTagValue(PROPERTY_NAME);
  7864. }
  7865. if (!strcmp((LPCSTR)szPropertyName,
  7866. (LPCSTR)pChildToken->GetTagValue(PROPERTY_NAME)))
  7867. {
  7868. // If we only need a name match then we're done.
  7869. if (fNameMatchOnly)
  7870. break;
  7871. // If both are properties and the types are similar or an
  7872. // enum then the signature is the same we found a match.
  7873. if ((pChildToken->IsSet(PROPERTY_GETSETMETHODS) == pToFindToken->IsSet(PROPERTY_GETSETMETHODS)) &&
  7874. (pChildToken->IsSet(PROPERTY_MEMBER) == pToFindToken->IsSet(PROPERTY_MEMBER)) &&
  7875. (pChildToken->IsSet(PROPERTY_GET) == pToFindToken->IsSet(PROPERTY_GET)) &&
  7876. (pChildToken->IsSet(PROPERTY_SET) == pToFindToken->IsSet(PROPERTY_SET)))
  7877. {
  7878. if (!strcmp((LPCSTR)pChildToken->GetTagValue(PROPERTY_ATYPE),
  7879. (LPCSTR)pToFindToken->GetTagValue(PROPERTY_ATYPE)))
  7880. break;
  7881. if (FindEnum(pChildToken) && FindEnum(pToFindToken))
  7882. break;
  7883. }
  7884. }
  7885. }
  7886. }
  7887. }
  7888. return pChildToken;
  7889. }