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.

822 lines
28 KiB

  1. #include <assert.h>
  2. #include <iostream.h>
  3. #include "IComp.Hxx"
  4. extern bool fgMethodAttribute;
  5. extern bool fgMethodParameter;
  6. bool CompareBuffer( char* pBuff1, char* pBuff2, unsigned long nLen);
  7. bool CompareBufferNoCase( char* pBuff1, char* pBuff2, unsigned long nLen);
  8. void WriteLine(HANDLE file, char* pBuff, int nLen);
  9. void TokenizeAttributes( char* pBuf, unsigned long nCnt, CAutoArray<ATTRINFO>* pList );
  10. extern unsigned long g_ulAppRetVal;
  11. extern bool fgParamNames;
  12. extern bool fgParamTypes;
  13. extern bool fgParamNameCase;
  14. extern bool fgParamTypeCase;
  15. CCompareInterface::CCompareInterface( char* pCurBuf,
  16. char* pRefBuf,
  17. HANDLE fileDiff,
  18. char* pszIntName,
  19. BLOCK_TYPE blockType,
  20. char* pszMethodAttr)
  21. {
  22. _pCurBuf = pCurBuf;
  23. _pRefBuf = pRefBuf;
  24. _fileDiff = fileDiff;
  25. _pszIntName = pszIntName;
  26. _blockType = blockType;
  27. _pszMethodAttr = pszMethodAttr;
  28. _pCurList = new CAutoArray<LINEINFO>;
  29. _pRefList = new CAutoArray<LINEINFO>;
  30. CreateLineIndex(_pCurList, _pCurBuf);
  31. CreateLineIndex(_pRefList, _pRefBuf);
  32. _bFirstTime = true;
  33. }
  34. CCompareInterface::~CCompareInterface()
  35. {
  36. delete _pCurList;
  37. delete _pRefList;
  38. }
  39. void CCompareInterface::FindAdditionsAndChanges( )
  40. {
  41. long lIdx;
  42. long lTmp;
  43. LINEINFO lineCur;
  44. LINEINFO lineRef;
  45. bool bRetVal = false;
  46. //check for additions and alterations
  47. for ( lIdx = 0; lIdx< (int)_pCurList->Size(); lIdx++)
  48. {
  49. _pCurList->GetAt( lIdx, &lineCur );
  50. //get the real name of the method or property
  51. char* pszMethodName = new char[lineCur.ulParamStart-lineCur.ulMethodNameStart+1];
  52. for (lTmp=lineCur.ulMethodNameStart; lTmp<(long)lineCur.ulParamStart; lTmp++)
  53. {
  54. pszMethodName[lTmp-lineCur.ulMethodNameStart] = _pCurBuf[lTmp];
  55. }
  56. pszMethodName[lTmp-lineCur.ulMethodNameStart] = 0;
  57. lstrcpy( _szLogBuff, _pszIntName);
  58. lstrcat( _szLogBuff, "::" );
  59. lstrcat( _szLogBuff, pszMethodName );
  60. for ( lTmp=0; lTmp<_pRefList->Size(); lTmp++ )
  61. {
  62. _pRefList->GetAt( lTmp, &lineRef );
  63. //compare the names of two methods to find if they are comparable
  64. //in respect to other aspects of their declarations.
  65. if ((!lineRef.fUsed)&&
  66. ( CompareBuffer( pszMethodName,
  67. &_pRefBuf[lineRef.ulMethodNameStart],
  68. max( lineCur.ulParamStart-lineCur.ulMethodNameStart, lineRef.ulParamStart-lineRef.ulMethodNameStart) )))
  69. {
  70. // if the names are the same, now compare the return values. If they are not the same, then the method is
  71. // modified from its original version.
  72. if ( !CompareBuffer( &_pCurBuf[lineCur.ulNameStart],
  73. &_pRefBuf[lineRef.ulNameStart],
  74. max( lineCur.ulMethodNameStart-lineCur.ulNameStart, lineRef.ulMethodNameStart-lineRef.ulNameStart) ))
  75. {
  76. bRetVal = true;
  77. }
  78. //compare attribute block
  79. if (( fgMethodAttribute ) &&
  80. ((lineCur.ulAttrEnd-lineCur.ulAttrStart != lineRef.ulAttrEnd-lineRef.ulAttrStart) ||
  81. ( !CompareBuffer( &_pCurBuf[lineCur.ulAttrStart], &_pRefBuf[lineRef.ulAttrStart],
  82. max(lineCur.ulAttrEnd-lineCur.ulAttrStart, lineRef.ulAttrEnd-lineRef.ulAttrStart)))) )
  83. {
  84. // since we know the attributes have changed, analyze the type of change
  85. CompareMethodAttributes( &lineRef, &lineCur );
  86. }
  87. //compare parameter block
  88. if (( fgMethodParameter ) &&
  89. ((lineCur.ulParamEnd-lineCur.ulParamStart != lineRef.ulParamEnd-lineRef.ulParamStart) ||
  90. ( !CompareBuffer( &_pCurBuf[lineCur.ulParamStart], &_pRefBuf[lineRef.ulParamStart],
  91. max(lineCur.ulParamEnd-lineCur.ulParamStart, lineRef.ulParamEnd-lineRef.ulParamStart)))) )
  92. {
  93. CompareMethodParameters( &lineRef, &lineCur );
  94. }
  95. //we have found the method that matches, move on to the next
  96. //method name on the current block.
  97. lineRef.fUsed = true;
  98. _pRefList->Set( lTmp, lineRef );
  99. break;
  100. }
  101. }
  102. //write the results that were found from this comparison,
  103. //if this was a different line
  104. if ( bRetVal || (lTmp == _pRefList->Size()) )
  105. {
  106. char* pszBuff = new char[128];
  107. EnsureTitle( TRUE );
  108. if ( bRetVal )
  109. {
  110. lstrcpy( pszBuff, _szLogBuff );
  111. lstrcat( pszBuff, " - Return value or call type has changed " );
  112. WriteLine( _fileDiff, pszBuff, -1);
  113. bRetVal = false;
  114. g_ulAppRetVal |= CHANGE_RETVALCHANGE;
  115. }
  116. if (lTmp == _pRefList->Size()) //this is a new nethod
  117. {
  118. lstrcpy( pszBuff, _szLogBuff );
  119. lstrcat( pszBuff, " - Is a new method " );
  120. WriteLine(_fileDiff, pszBuff,-1);
  121. if ( _blockType== BLK_DISPINT )
  122. g_ulAppRetVal |= CHANGE_METHODONDISPINT;
  123. else
  124. g_ulAppRetVal |= CHANGE_METHODONINT;
  125. }
  126. delete [] pszBuff;
  127. }
  128. delete [] pszMethodName;
  129. }
  130. }
  131. //----------------------------------------------------------------------------
  132. // bMode == TRUE --> Addition / Change
  133. //----------------------------------------------------------------------------
  134. void
  135. CCompareInterface::EnsureTitle( BOOL bAddition )
  136. {
  137. char szBuff[256];
  138. if ( _bFirstTime )
  139. {
  140. //write the header.
  141. if ( _blockType== BLK_DISPINT )
  142. lstrcpy( szBuff, "\nDispinterface " );
  143. else
  144. lstrcpy( szBuff, "\nInterface " );
  145. lstrcat( szBuff, _pszIntName );
  146. lstrcat( szBuff, "\n------------------------------------\n");
  147. if ( bAddition )
  148. {
  149. lstrcat( szBuff, "Additions / Changes:" );
  150. }
  151. WriteLine( _fileDiff, szBuff, -1);
  152. _bFirstTime = false;
  153. }
  154. }
  155. //
  156. // Walk through the unmarked elements of the reference block index. These are the
  157. // entries that do not exist in the current block.
  158. //
  159. void CCompareInterface::FindRemovals( )
  160. {
  161. long lIdx;
  162. long lTmp;
  163. LINEINFO lineRef;
  164. char* szBuff = new char[128];
  165. bool bFirstRemoval = true;
  166. for ( lIdx=0; lIdx< (int)_pRefList->Size(); lIdx++ )
  167. {
  168. //get the record
  169. _pRefList->GetAt( lIdx, &lineRef);
  170. //is the record marked ?
  171. if (!lineRef.fUsed)
  172. {
  173. //get the real name of the interface
  174. char* pszMethodName = new char[lineRef.ulParamStart-lineRef.ulMethodNameStart+1];
  175. int nIdx;
  176. for (lTmp=lineRef.ulMethodNameStart, nIdx=0; lTmp<(long)lineRef.ulParamStart; lTmp++, nIdx++)
  177. {
  178. pszMethodName[nIdx] = _pRefBuf[lTmp];
  179. }
  180. pszMethodName[nIdx] = 0; //terminate the string
  181. // if this is the first removal, then add the word Removals
  182. EnsureTitle( FALSE );
  183. //write the header.
  184. if ( _blockType== BLK_DISPINT )
  185. g_ulAppRetVal |= CHANGE_REMOVEFROMDISPINT;
  186. else
  187. g_ulAppRetVal |= CHANGE_REMOVEFROMINT;
  188. if ( bFirstRemoval)
  189. {
  190. WriteLine( _fileDiff, "Removals : ", -1);
  191. bFirstRemoval = false;
  192. }
  193. lstrcpy( szBuff, _pszIntName);
  194. lstrcat( szBuff, "::");
  195. lstrcat( szBuff, pszMethodName);
  196. lstrcat( szBuff, " has been removed.");
  197. WriteLine( _fileDiff, szBuff, -1);
  198. delete [] pszMethodName;
  199. }
  200. }
  201. delete [] szBuff;
  202. }
  203. void CCompareInterface::CreateLineIndex( CAutoArray<LINEINFO>* pList, char* pBuf )
  204. {
  205. LINEINFO lineinfo = {0};
  206. unsigned long ulIdx=0;
  207. unsigned long ulLastSpace = 0;
  208. char chSearch = '['; //initially look for the opening attribute char.
  209. unsigned int uBrCnt = 0;
  210. unsigned int uParCnt = 0;
  211. //go until the end of the buffer, it is null terminated.
  212. while ( pBuf[ulIdx] != 0)
  213. {
  214. if ( pBuf[ulIdx] == chSearch )
  215. {
  216. //depending on what we were looking for,
  217. //we can decide what to look for next.
  218. switch (chSearch)
  219. {
  220. case '[':
  221. uBrCnt++;
  222. if ( uBrCnt == 1 )
  223. {
  224. lineinfo.ulAttrStart = ulIdx;
  225. chSearch = ']';
  226. }
  227. break;
  228. case ']':
  229. uBrCnt --;
  230. if ( uBrCnt == 0 )
  231. {
  232. lineinfo.ulAttrEnd = ulIdx;
  233. lineinfo.ulNameStart = ulIdx+2;
  234. chSearch = '(';
  235. }
  236. break;
  237. case '(':
  238. uParCnt++;
  239. if (uParCnt==1)
  240. {
  241. lineinfo.ulNameEnd = ulIdx-1;
  242. lineinfo.ulParamStart = ulIdx;
  243. lineinfo.ulMethodNameStart = ulLastSpace+1;
  244. chSearch = ')';
  245. }
  246. break;
  247. case ')':
  248. uParCnt--;
  249. if ( uParCnt == 0 )
  250. {
  251. lineinfo.ulParamEnd = ulIdx;
  252. chSearch = '[';
  253. //completed the cycle, add this record to the list
  254. pList->Append(lineinfo);
  255. }
  256. break;
  257. }
  258. }
  259. else
  260. {
  261. switch ( pBuf[ulIdx] )
  262. {
  263. case '(':
  264. uParCnt++;
  265. break;
  266. case ')':
  267. uParCnt--;
  268. break;
  269. case '[':
  270. uBrCnt++;
  271. break;
  272. case ']':
  273. uBrCnt--;
  274. break;
  275. case ' ':
  276. ulLastSpace = ulIdx;
  277. break;
  278. }
  279. }
  280. ulIdx++;
  281. }
  282. }
  283. /*----------------------------------------------------------------------------
  284. ----------------------------------------------------------------------------*/
  285. void
  286. CCompareInterface::CompareMethodAttributes( LINEINFO* pRef,
  287. LINEINFO* pCur )
  288. {
  289. long l,
  290. k;
  291. long curBase = (pCur->ulAttrStart)+1;
  292. long refBase = (pRef->ulAttrStart)+1;
  293. ATTRINFO attrRef;
  294. ATTRINFO attrCur;
  295. CAutoArray<ATTRINFO>* pCurList = new CAutoArray<ATTRINFO>;
  296. CAutoArray<ATTRINFO>* pRefList = new CAutoArray<ATTRINFO>;
  297. TokenizeAttributes( &_pRefBuf[refBase], pRef->ulAttrEnd-refBase, pRefList );
  298. TokenizeAttributes( &_pCurBuf[curBase], pCur->ulAttrEnd-curBase, pCurList );
  299. //let's find the ones that are new
  300. for ( l=0; l < pCurList->Size(); l++ )
  301. {
  302. pCurList->GetAt( l, &attrCur);
  303. for ( k=0; k < pRefList->Size(); k++ )
  304. {
  305. pRefList->GetAt( k, &attrRef );
  306. if ( (!attrRef.fUsed ) &&
  307. CompareBuffer( &_pCurBuf[curBase + attrCur.ulAttrStart],
  308. &_pRefBuf[refBase + attrRef.ulAttrStart],
  309. max( attrCur.ulAttrLength, attrRef.ulAttrLength)) )
  310. {
  311. // found the same attribute in the reference attributes, it is not a new
  312. // attribute
  313. attrRef.fUsed = true;
  314. pRefList->Set( k, attrRef );
  315. attrCur.fUsed = true;
  316. pCurList->Set( l, attrCur );
  317. break;
  318. }
  319. }
  320. if ( k == pRefList->Size() )
  321. {
  322. // this is a new attribute.
  323. // if we find this attribute name in the list, then we are breaking the compat
  324. if ( IsAttributeBreaker( _pszMethodAttr,
  325. _pCurBuf+curBase+attrCur.ulAttrStart,
  326. attrCur.ulAttrLength ) )
  327. {
  328. EnsureTitle(TRUE);
  329. WriteAttrChangeString( _pCurBuf,
  330. curBase+attrCur.ulAttrStart,
  331. attrCur.ulAttrLength,
  332. "' attribute was added");
  333. }
  334. }
  335. }
  336. // Whatever is left in the reference array as not used are removals.
  337. for ( l=0; l < pRefList->Size(); l++ )
  338. {
  339. pRefList->GetAt( l, &attrRef);
  340. if ( !attrRef.fUsed )
  341. {
  342. // if we find this attribute name in the list, then we are breaking the compat
  343. if ( IsAttributeBreaker( _pszMethodAttr,
  344. _pRefBuf+refBase+attrRef.ulAttrStart,
  345. attrRef.ulAttrLength ) )
  346. {
  347. // breaker attribute
  348. EnsureTitle(TRUE);
  349. WriteAttrChangeString( _pRefBuf,
  350. refBase+attrRef.ulAttrStart,
  351. attrRef.ulAttrLength,
  352. "' attribute was removed");
  353. }
  354. }
  355. }
  356. delete pCurList;
  357. delete pRefList;
  358. }
  359. //----------------------------------------------------------------------------
  360. // The attribute list contains the buffer that is read from the INI file.
  361. // Each attribute name is a string that is terminated by a NULL character. At
  362. // the very end, after the last attribute, there is an additional NULL.
  363. //----------------------------------------------------------------------------
  364. BOOL
  365. CCompareInterface::IsAttributeBreaker( char * pszAttrList, char * pszAttr, unsigned long ulAttrLen )
  366. {
  367. unsigned long ulStrLen;
  368. unsigned long ulIdx = 0; // index to the big buffer.
  369. // until we reach the very end.
  370. // if we can not get into the loop below, it means that there are no
  371. // attributes that are considered breaking
  372. while (pszAttrList[ulIdx] != NULL)
  373. {
  374. ulStrLen = lstrlen(&pszAttrList[ulIdx]);
  375. // if the lengths and the contents are the same, then this attribute
  376. // is a breaker attribute
  377. if ((ulStrLen == ulAttrLen) &&
  378. (CompareBuffer(&pszAttrList[ulIdx], pszAttr, ulStrLen)))
  379. {
  380. return TRUE;
  381. }
  382. // increment the index, to point to the next string in the buffer
  383. ulIdx += ulStrLen + 1;
  384. }
  385. // if we reach here, it means that we could not find the attribute in the list
  386. // this is NOT a breaker attribute
  387. return FALSE;
  388. }
  389. void
  390. CCompareInterface::WriteAttrChangeString(char* pBuf,
  391. unsigned long ulAttrStart,
  392. unsigned long ulAttrLength,
  393. char* szChangeType)
  394. {
  395. unsigned long k;
  396. char szBuff[256];
  397. char * pszAttrName = new char[ulAttrLength+1];
  398. //copy the attribute name into the buffer
  399. for (k = 0; k < ulAttrLength; k++)
  400. pszAttrName[k] = *(pBuf + ulAttrStart + k);
  401. pszAttrName[k] = 0; //terminate
  402. lstrcpy(szBuff, _szLogBuff);
  403. lstrcat(szBuff, " - '");
  404. lstrcat(szBuff, pszAttrName);
  405. lstrcat(szBuff, szChangeType);
  406. WriteLine(_fileDiff, szBuff, -1);
  407. g_ulAppRetVal |= CHANGE_ATTRCHANGE;
  408. }
  409. //----------------------------------------------------------------------------
  410. //----------------------------------------------------------------------------
  411. void
  412. CCompareInterface::CompareMethodParameters( LINEINFO* pRef, LINEINFO* pCur)
  413. {
  414. long l;
  415. long k;
  416. long curBase = (pCur->ulParamStart)+1;
  417. long refBase = (pRef->ulParamStart)+1;
  418. PARAMINFO paramRef;
  419. PARAMINFO paramCur;
  420. CAutoArray<PARAMINFO>* pCurList = NULL;
  421. CAutoArray<PARAMINFO>* pRefList = NULL;
  422. bool bNameChange,
  423. bTypeChange,
  424. bReplaced;
  425. char szBuff[512] = {0};
  426. char szType[64] = {0};
  427. char szName[64] = {0};
  428. pCurList = new CAutoArray<PARAMINFO>;
  429. pRefList = new CAutoArray<PARAMINFO>;
  430. assert( pCurList );
  431. assert( pRefList );
  432. // start by tokenizing the parameters
  433. TokenizeParameters( &_pRefBuf[refBase], pRef->ulParamEnd-refBase, pRefList);
  434. TokenizeParameters( &_pCurBuf[curBase], pCur->ulParamEnd-curBase, pCurList);
  435. // parameters have to match one to one.
  436. for ( l=0; l<pRefList->Size(); l++ )
  437. {
  438. bTypeChange = bNameChange = bReplaced = false;
  439. pCurList->GetAt( l, &paramCur);
  440. pRefList->GetAt( l, &paramRef);
  441. // is this parameter touched before, because of a replacement catch?
  442. // if that is the case we should only check if the reference parameter was replaced
  443. if ( paramCur.fUsed )
  444. {
  445. bTypeChange = bNameChange = true;
  446. goto ReplaceCheck;
  447. }
  448. // compare the types
  449. if ( fgParamTypes )
  450. {
  451. //
  452. // Only go through comparison if the type does not contain a _MIDL_ word in it.
  453. //
  454. char szTypeRef[64] = {0};
  455. lstrcpyn( szTypeRef,
  456. _pRefBuf+refBase+paramRef.ulTypeStart,
  457. max(63, paramRef.ulTypeLength));
  458. if ( !strstr(szTypeRef, "_MIDL_") )
  459. {
  460. // if the lengths are different bail out immediately, without text comparison.
  461. if ( paramRef.ulTypeLength == paramCur.ulTypeLength )
  462. {
  463. //compare the contents, check if we want case sensitive or not.
  464. if ( fgParamTypeCase )
  465. bTypeChange = !CompareBuffer( _pRefBuf+refBase+paramRef.ulTypeStart,
  466. _pCurBuf+curBase+paramCur.ulTypeStart,
  467. max( paramRef.ulTypeLength, paramCur.ulTypeLength) );
  468. else
  469. bTypeChange = !CompareBufferNoCase( _pRefBuf+refBase+paramRef.ulTypeStart,
  470. _pCurBuf+curBase+paramCur.ulTypeStart,
  471. max( paramRef.ulTypeLength, paramCur.ulTypeLength) );
  472. }
  473. else
  474. bTypeChange = true;
  475. }
  476. else
  477. {
  478. // if one of the types contains a _MIDL_, then the other MUST too.
  479. char szTypeCur[64] = {0};
  480. lstrcpyn( szTypeCur,
  481. _pCurBuf+curBase+paramCur.ulTypeStart,
  482. max(63, paramCur.ulTypeLength));
  483. // if the string does NOT contain _MIDL_ than there was a change.
  484. if ( !strstr(szTypeCur, "_MIDL_") )
  485. {
  486. bTypeChange = true;
  487. }
  488. }
  489. }
  490. if ( fgParamNames )
  491. {
  492. char szNameRef[64] = {0};
  493. //
  494. // If the name of one parameter contains a _MIDL_ keyword, then only make sure the
  495. // other name contains the _MIDL_ too. No need to match strings.
  496. //
  497. lstrcpyn( szNameRef, _pRefBuf+refBase+paramRef.ulNameStart, max(63, paramRef.ulNameLength));
  498. if (!strstr(szNameRef, "_MIDL_"))
  499. {
  500. // if the lengths are different bail out immediately, without text comparison.
  501. if ( paramRef.ulNameLength == paramCur.ulNameLength )
  502. {
  503. //compare the contents, check if we want case sensitive or not.
  504. if ( fgParamNameCase )
  505. bNameChange = !CompareBuffer( _pRefBuf+refBase+paramRef.ulNameStart,
  506. _pCurBuf+curBase+paramCur.ulNameStart,
  507. max( paramRef.ulNameLength, paramCur.ulNameLength) );
  508. else
  509. bNameChange = !CompareBuffer( _pRefBuf+refBase+paramRef.ulNameStart,
  510. _pCurBuf+curBase+paramCur.ulNameStart,
  511. max( paramRef.ulNameLength, paramCur.ulNameLength) );
  512. }
  513. else
  514. bNameChange = true;
  515. }
  516. else
  517. {
  518. char szNameCur[64] = {0};
  519. // only make sure the current name also has the _MIDL_ keyword.
  520. lstrcpyn( szNameCur, _pCurBuf+curBase+paramCur.ulNameStart, max(63, paramCur.ulNameLength));
  521. if (!strstr( szNameCur, "_MIDL_"))
  522. {
  523. bNameChange = true;
  524. }
  525. }
  526. }
  527. ReplaceCheck:
  528. // if there was a change in the parameter, find out if this parameter is moved to another location
  529. // in the parameter list. We look for an exact match in this case, since this is only additional
  530. // information
  531. if ( bNameChange || bTypeChange )
  532. {
  533. PARAMINFO paramTmp;
  534. for ( k=0; k< pCurList->Size(); k++ )
  535. {
  536. pCurList->GetAt( k, &paramTmp );
  537. if ( ( !paramTmp.fUsed ) &&
  538. ( paramTmp.ulParamLength == paramCur.ulParamLength ) &&
  539. ( CompareBuffer( _pRefBuf+refBase+paramRef.ulTypeStart,
  540. _pCurBuf+curBase+paramTmp.ulTypeStart,
  541. paramTmp.ulParamLength) ) )
  542. {
  543. // we have found the parameter at another location.
  544. bReplaced = true;
  545. // we will only report the replacement, to simplify
  546. bTypeChange = false;
  547. bNameChange = false;
  548. // mark the parameter in the current list as touched, so that
  549. // whatever parameter we check in the reference list does not get
  550. // processed against this. ( perf. )
  551. paramTmp.fUsed = true;
  552. pCurList->Set( k, paramTmp );
  553. }
  554. }
  555. }
  556. // if we found the parameter at the same location
  557. if ( bReplaced || bNameChange || bTypeChange )
  558. {
  559. EnsureTitle(TRUE);
  560. g_ulAppRetVal |= CHANGE_PARAMCHANGE;
  561. // we copy the type and the name. The lengths are +1 since the function requires
  562. // us to calculate the NULL character too.
  563. lstrcpyn( szType, _pRefBuf+refBase+paramRef.ulTypeStart, paramRef.ulTypeLength+1 );
  564. if ( paramRef.ulNameStart )
  565. lstrcpyn( szName, _pRefBuf+refBase+paramRef.ulNameStart, paramRef.ulNameLength+1 );
  566. // fill the string with ' - Parameter xx', so that we can add the change type
  567. lstrcpy( szBuff, _szLogBuff);
  568. lstrcat( szBuff, " - Parameter " );
  569. lstrcat( szBuff, szType );
  570. lstrcat( szBuff, " ");
  571. lstrcat( szBuff, szName );
  572. // if replaced, then name and type change flags are false.
  573. if ( bReplaced )
  574. {
  575. // output replacement information
  576. lstrcat( szBuff, " has been replaced" );
  577. }
  578. else
  579. {
  580. // was this parameter removed
  581. if ( bNameChange && bTypeChange )
  582. {
  583. // output information that shows the name change
  584. lstrcat( szBuff, " has been removed");
  585. }
  586. else
  587. {
  588. if ( bNameChange )
  589. {
  590. // output information that shows the name change
  591. lstrcat( szBuff, " name has been modified");
  592. // for name only changes, mark the parameter as used.
  593. paramCur.fUsed = true;
  594. pCurList->Set( l, paramCur );
  595. }
  596. if ( bTypeChange )
  597. {
  598. // output information that shows the type change.
  599. lstrcat( szBuff, " type has been modified");
  600. }
  601. }
  602. }
  603. WriteLine(_fileDiff, szBuff, -1);
  604. }
  605. else
  606. {
  607. // mark the parameter, everything is OK, move on.
  608. paramCur.fUsed = true;
  609. pCurList->Set( l, paramCur );
  610. }
  611. }
  612. // find the parameters that were added.
  613. for ( l=0; l<pCurList->Size(); l++ )
  614. {
  615. pCurList->GetAt( l, &paramCur);
  616. // if this parameter was not used, then it means that it was added.
  617. if ( !paramCur.fUsed )
  618. {
  619. EnsureTitle(TRUE);
  620. g_ulAppRetVal |= CHANGE_PARAMCHANGE;
  621. // copy the parameter name as a whole
  622. lstrcpyn( szName, _pCurBuf+curBase+paramCur.ulTypeStart, paramCur.ulParamLength+1 );
  623. // fill the string with ' - Parameter xx', so that we can add the change type
  624. lstrcpy( szBuff, _szLogBuff);
  625. lstrcat( szBuff, " - Parameter " );
  626. lstrcat( szBuff, szName );
  627. lstrcat( szBuff, " was added");
  628. WriteLine( _fileDiff, szBuff, -1);
  629. }
  630. }
  631. delete pCurList;
  632. delete pRefList;
  633. }
  634. //----------------------------------------------------------------------------
  635. //----------------------------------------------------------------------------
  636. void
  637. CCompareInterface::TokenizeParameters( char* pBuf,
  638. unsigned long nCnt,
  639. CAutoArray<PARAMINFO>* pList )
  640. {
  641. unsigned long i,j;
  642. PARAMINFO paramInfo;
  643. bool bInBracket = false;
  644. paramInfo.ulTypeStart = 0;
  645. for( i=0; i<=nCnt ; i++ )
  646. {
  647. // since we are coming from left, and going right, we will first see the
  648. // opening and then the closing bracket
  649. if ( pBuf[i] == '[' )
  650. bInBracket = true;
  651. if ( pBuf[i] == ']' )
  652. bInBracket = false;
  653. // if we reached a comma that was not inside a bracket, or reached the end
  654. // and the end is an opening parenthesis
  655. if ( ((pBuf[i] == ',') && !bInBracket ) || ( i == nCnt ) )
  656. {
  657. paramInfo.ulParamLength = i - paramInfo.ulTypeStart;
  658. paramInfo.fUsed = false;
  659. // digest the type and name here ! ! !
  660. for ( j = paramInfo.ulTypeStart+paramInfo.ulParamLength-1; j > 0 ; j-- )
  661. {
  662. // go from the end of the parameter, towards the beginning,
  663. // searching for a space character, or the beginning of the parameter block
  664. if ( *(pBuf + j) == ' ')
  665. {
  666. paramInfo.ulNameStart = j + 1;
  667. paramInfo.ulTypeLength = j - paramInfo.ulTypeStart;
  668. paramInfo.ulNameLength = paramInfo.ulTypeStart + paramInfo.ulParamLength - paramInfo.ulNameStart;
  669. break;
  670. }
  671. }
  672. // we could not find a parameter when we parsed through, it means a void..
  673. // double check for void
  674. if (( j==0 ) && ( *pBuf == 'v' ) && (*(pBuf+1) == 'o'))
  675. {
  676. paramInfo.ulTypeStart = 0;
  677. paramInfo.ulTypeLength = 4;
  678. paramInfo.ulParamLength = 4;
  679. paramInfo.ulNameStart = 0;
  680. paramInfo.ulNameLength = 0;
  681. pList->Append( paramInfo );
  682. }
  683. else
  684. {
  685. // we should never ever reach zero.
  686. if ( j==0 )
  687. assert( false );
  688. pList->Append( paramInfo );
  689. // skip over the comma
  690. i++;
  691. // the name starts next to the space
  692. paramInfo.ulTypeStart = i+1;
  693. }
  694. }
  695. }
  696. }