Team Fortress 2 Source Code as on 22/4/2020
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.

828 lines
22 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #ifdef _LINUX
  8. #include <ctime> // needed by xercesc
  9. #endif
  10. #include "stdafx.h"
  11. #include "tier0/platform.h"
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #ifdef _WIN32
  17. #include <windows.h>
  18. #include <comutil.h> // _variant_t
  19. #include <atlbase.h> // CComPtr
  20. #elif _LINUX
  21. #include <unistd.h>
  22. #include <dirent.h> // scandir()
  23. #define _stat stat
  24. #include <xercesc/util/PlatformUtils.hpp>
  25. #include <xercesc/util/XMLString.hpp>
  26. #include <xercesc/dom/DOM.hpp>
  27. #include <xercesc/sax/HandlerBase.hpp>
  28. #include <xercesc/parsers/XercesDOMParser.hpp>
  29. #include "valve_minmax_off.h"
  30. #if defined(XERCES_NEW_IOSTREAMS)
  31. #include <iostream>
  32. #else
  33. #include <iostream.h>
  34. #endif
  35. #include "valve_minmax_on.h"
  36. #define IXMLDOMNode DOMNode
  37. #define IXMLDOMNodeList DOMNodeList
  38. #define _alloca alloca
  39. XERCES_CPP_NAMESPACE_USE
  40. class XStr
  41. {
  42. public :
  43. XStr(const char* const toTranscode)
  44. {
  45. // Call the private transcoding method
  46. fUnicodeForm = XMLString::transcode(toTranscode);
  47. }
  48. ~XStr()
  49. {
  50. XMLString::release(&fUnicodeForm);
  51. }
  52. // -----------------------------------------------------------------------
  53. // Getter methods
  54. // -----------------------------------------------------------------------
  55. const XMLCh* unicodeForm() const
  56. {
  57. return fUnicodeForm;
  58. }
  59. private :
  60. XMLCh* fUnicodeForm;
  61. };
  62. #define _bstr_t(str) XStr(str).unicodeForm()
  63. #else
  64. #error "Unsupported platform"
  65. #endif
  66. #include "vcprojconvert.h"
  67. #include "utlvector.h"
  68. //-----------------------------------------------------------------------------
  69. // Purpose: constructor
  70. //-----------------------------------------------------------------------------
  71. CVCProjConvert::CVCProjConvert()
  72. {
  73. #ifdef _WIN32
  74. ::CoInitialize(NULL);
  75. #elif _LINUX
  76. try {
  77. XMLPlatformUtils::Initialize();
  78. }
  79. catch (const XMLException& toCatch) {
  80. char* message = XMLString::transcode(toCatch.getMessage());
  81. Error( "Error during initialization! : %s\n", message);
  82. XMLString::release(&message);
  83. }
  84. #endif
  85. m_bProjectLoaded = false;
  86. }
  87. //-----------------------------------------------------------------------------
  88. // Purpose: destructor
  89. //-----------------------------------------------------------------------------
  90. CVCProjConvert::~CVCProjConvert()
  91. {
  92. #ifdef _WIN32
  93. ::CoUninitialize();
  94. #elif _LINUX
  95. // nothing to shutdown
  96. #endif
  97. }
  98. //-----------------------------------------------------------------------------
  99. // Purpose: load up a project and parse it
  100. //-----------------------------------------------------------------------------
  101. bool CVCProjConvert::LoadProject( const char *project )
  102. {
  103. #ifdef _WIN32
  104. HRESULT hr;
  105. IXMLDOMDocument *pXMLDoc=NULL;
  106. hr = ::CoCreateInstance(CLSID_DOMDocument,
  107. NULL,
  108. CLSCTX_INPROC_SERVER,
  109. IID_IXMLDOMDocument,
  110. (void**)&pXMLDoc);
  111. if (FAILED(hr))
  112. {
  113. Msg ("Cannot instantiate msxml2.dll\n");
  114. Msg ("Please download the MSXML run-time (url below)\n");
  115. Msg ("http://msdn.microsoft.com/downloads/default.asp?url=/downloads/sample.asp?url=/msdn-files/027/001/766/msdncompositedoc.xml\n");
  116. return false;
  117. }
  118. VARIANT_BOOL vtbool;
  119. _variant_t bstrProject(project);
  120. pXMLDoc->put_async( VARIANT_BOOL(FALSE) );
  121. hr = pXMLDoc->load(bstrProject,&vtbool);
  122. if (FAILED(hr) || vtbool==VARIANT_FALSE)
  123. {
  124. Msg ("Could not open %s.\n", bstrProject);
  125. pXMLDoc->Release();
  126. return false;
  127. }
  128. #elif _LINUX
  129. XercesDOMParser* parser = new XercesDOMParser();
  130. parser->setValidationScheme(XercesDOMParser::Val_Always); // optional.
  131. parser->setDoNamespaces(true); // optional
  132. ErrorHandler* errHandler = (ErrorHandler*) new HandlerBase();
  133. parser->setErrorHandler(errHandler);
  134. try {
  135. parser->parse(project);
  136. }
  137. catch (const XMLException& toCatch) {
  138. char* message = XMLString::transcode(toCatch.getMessage());
  139. Error( "Exception message is: %s\n", message );
  140. XMLString::release(&message);
  141. return;
  142. }
  143. catch (const DOMException& toCatch) {
  144. char* message = XMLString::transcode(toCatch.msg);
  145. Error( "Exception message is: %s\n", message );
  146. XMLString::release(&message);
  147. return;
  148. }
  149. catch (...) {
  150. Error( "Unexpected Exception \n" );
  151. return;
  152. }
  153. DOMDocument *pXMLDoc = parser->getDocument();
  154. #endif
  155. ExtractProjectName( pXMLDoc );
  156. if ( !m_Name.IsValid() )
  157. {
  158. Msg( "Failed to extract project name\n" );
  159. return false;
  160. }
  161. char baseDir[ MAX_PATH ];
  162. Q_ExtractFilePath( project, baseDir, sizeof(baseDir) );
  163. Q_StripTrailingSlash( baseDir );
  164. m_BaseDir = baseDir;
  165. ExtractConfigurations( pXMLDoc );
  166. if ( m_Configurations.Count() == 0 )
  167. {
  168. Msg( "Failed to find any configurations to load\n" );
  169. return false;
  170. }
  171. ExtractFiles( pXMLDoc );
  172. #ifdef _WIN32
  173. pXMLDoc->Release();
  174. #elif _LINUX
  175. delete pXMLDoc;
  176. delete errHandler;
  177. #endif
  178. m_bProjectLoaded = true;
  179. return true;
  180. }
  181. //-----------------------------------------------------------------------------
  182. // Purpose: returns the number of different configurations loaded
  183. //-----------------------------------------------------------------------------
  184. int CVCProjConvert::GetNumConfigurations()
  185. {
  186. Assert( m_bProjectLoaded );
  187. return m_Configurations.Count();
  188. }
  189. //-----------------------------------------------------------------------------
  190. // Purpose: returns the index of a config with this name, -1 on err
  191. //-----------------------------------------------------------------------------
  192. int CVCProjConvert::FindConfiguration( CUtlSymbol name )
  193. {
  194. if ( !name.IsValid() )
  195. {
  196. return -1;
  197. }
  198. for ( int i = 0; i < m_Configurations.Count(); i++ )
  199. {
  200. if ( m_Configurations[i].GetName() == name )
  201. {
  202. return i;
  203. }
  204. }
  205. return -1;
  206. }
  207. //-----------------------------------------------------------------------------
  208. // Purpose: extracts the value of the xml attrib "attribName"
  209. //-----------------------------------------------------------------------------
  210. CUtlSymbol CVCProjConvert::GetXMLAttribValue( IXMLDOMElement *p, const char *attribName )
  211. {
  212. if (!p)
  213. {
  214. return CUtlSymbol();
  215. }
  216. #ifdef _WIN32
  217. VARIANT vtValue;
  218. p->getAttribute( _bstr_t(attribName), &vtValue);
  219. if ( vtValue.vt == VT_NULL )
  220. {
  221. return CUtlSymbol(); // element not found
  222. }
  223. Assert( vtValue.vt == VT_BSTR );
  224. CUtlSymbol name( static_cast<char *>( _bstr_t( vtValue.bstrVal ) ) );
  225. ::SysFreeString(vtValue.bstrVal);
  226. #elif _LINUX
  227. const XMLCh *xAttrib = XMLString::transcode( attribName );
  228. const XMLCh *value = p->getAttribute( xAttrib );
  229. if ( value == NULL )
  230. {
  231. return CUtlSymbol(); // element not found
  232. }
  233. char *transValue = XMLString::transcode(value);
  234. CUtlSymbol name( transValue );
  235. XMLString::release( &xAttrib );
  236. XMLString::release( &transValue );
  237. #endif
  238. return name;
  239. }
  240. //-----------------------------------------------------------------------------
  241. // Purpose: returns the name of this node
  242. //-----------------------------------------------------------------------------
  243. CUtlSymbol CVCProjConvert::GetXMLNodeName( IXMLDOMElement *p )
  244. {
  245. CUtlSymbol name;
  246. if (!p)
  247. {
  248. return name;
  249. }
  250. #ifdef _WIN32
  251. BSTR bstrName;
  252. p->get_nodeName( &bstrName );
  253. _bstr_t bstr(bstrName);
  254. name = static_cast<char *>(bstr);
  255. return name;
  256. #elif _LINUX
  257. Assert( 0 );
  258. Error( "Function CVCProjConvert::GetXMLNodeName not implemented\n" );
  259. return name;
  260. #endif
  261. }
  262. //-----------------------------------------------------------------------------
  263. // Purpose: returns the config object at this index
  264. //-----------------------------------------------------------------------------
  265. CVCProjConvert::CConfiguration & CVCProjConvert::GetConfiguration( int i )
  266. {
  267. Assert( m_bProjectLoaded );
  268. Assert( m_Configurations.IsValidIndex(i) );
  269. return m_Configurations[i];
  270. }
  271. //-----------------------------------------------------------------------------
  272. // Purpose: extracts the project name from the loaded vcproj
  273. //-----------------------------------------------------------------------------
  274. bool CVCProjConvert::ExtractProjectName( IXMLDOMDocument *pDoc )
  275. {
  276. #ifdef _WIN32
  277. CComPtr<IXMLDOMNodeList> pProj;
  278. pDoc->getElementsByTagName( _bstr_t("VisualStudioProject"), &pProj);
  279. if (pProj)
  280. {
  281. long len = 0;
  282. pProj->get_length(&len);
  283. Assert( len == 1 );
  284. if ( len == 1 )
  285. {
  286. CComPtr<IXMLDOMNode> pNode;
  287. pProj->get_item( 0, &pNode );
  288. if (pNode)
  289. {
  290. CComQIPtr<IXMLDOMElement> pElem( pNode );
  291. m_Name = GetXMLAttribValue( pElem, "Name");
  292. }
  293. }
  294. }
  295. #elif _LINUX
  296. DOMNodeList *nodes = pDoc->getElementsByTagName( _bstr_t("VisualStudioProject") );
  297. if ( nodes )
  298. {
  299. int len = nodes->getLength();
  300. if ( len == 1 )
  301. {
  302. DOMNode *node = nodes->item(0);
  303. if ( node )
  304. {
  305. m_Name = GetXMLAttribValue( node, "Name" );
  306. }
  307. }
  308. }
  309. #endif
  310. return true;
  311. }
  312. //-----------------------------------------------------------------------------
  313. // Purpose: extracts the list of configuration names from the vcproj
  314. //-----------------------------------------------------------------------------
  315. bool CVCProjConvert::ExtractConfigurations( IXMLDOMDocument *pDoc )
  316. {
  317. m_Configurations.RemoveAll();
  318. if (!pDoc)
  319. {
  320. return false;
  321. }
  322. #ifdef _WIN32
  323. CComPtr<IXMLDOMNodeList> pConfigs;
  324. pDoc->getElementsByTagName( _bstr_t("Configuration"), &pConfigs);
  325. if (pConfigs)
  326. {
  327. long len = 0;
  328. pConfigs->get_length(&len);
  329. for ( int i=0; i<len; i++ )
  330. {
  331. CComPtr<IXMLDOMNode> pNode;
  332. pConfigs->get_item( i, &pNode );
  333. if (pNode)
  334. {
  335. CComQIPtr<IXMLDOMElement> pElem( pNode );
  336. CUtlSymbol configName = GetXMLAttribValue( pElem, "Name" );
  337. if ( configName.IsValid() )
  338. {
  339. int newIndex = m_Configurations.AddToTail();
  340. CConfiguration & config = m_Configurations[newIndex];
  341. config.SetName( configName );
  342. ExtractIncludes( pElem, config );
  343. }
  344. }
  345. }
  346. }
  347. #elif _LINUX
  348. DOMNodeList *nodes = pDoc->getElementsByTagName( _bstr_t("Configuration"));
  349. if ( nodes )
  350. {
  351. int len = nodes->getLength();
  352. for ( int i=0; i<len; i++ )
  353. {
  354. DOMNode *node = nodes->item(i);
  355. if (node)
  356. {
  357. CUtlSymbol configName = GetXMLAttribValue( node, "Name" );
  358. if ( configName.IsValid() )
  359. {
  360. int newIndex = m_Configurations.AddToTail();
  361. CConfiguration & config = m_Configurations[newIndex];
  362. config.SetName( configName );
  363. ExtractIncludes( node, config );
  364. }
  365. }
  366. }
  367. }
  368. #endif
  369. return true;
  370. }
  371. //-----------------------------------------------------------------------------
  372. // Purpose: extracts the list of defines and includes used for this config
  373. //-----------------------------------------------------------------------------
  374. bool CVCProjConvert::ExtractIncludes( IXMLDOMElement *pDoc, CConfiguration & config )
  375. {
  376. config.ResetDefines();
  377. config.ResetIncludes();
  378. if (!pDoc)
  379. {
  380. return false;
  381. }
  382. #ifdef _WIN32
  383. CComPtr<IXMLDOMNodeList> pTools;
  384. pDoc->getElementsByTagName( _bstr_t("Tool"), &pTools);
  385. if (pTools)
  386. {
  387. long len = 0;
  388. pTools->get_length(&len);
  389. for ( int i=0; i<len; i++ )
  390. {
  391. CComPtr<IXMLDOMNode> pNode;
  392. pTools->get_item( i, &pNode );
  393. if (pNode)
  394. {
  395. CComQIPtr<IXMLDOMElement> pElem( pNode );
  396. CUtlSymbol toolName = GetXMLAttribValue( pElem, "Name" );
  397. if ( toolName == "VCCLCompilerTool" )
  398. {
  399. CUtlSymbol defines = GetXMLAttribValue( pElem, "PreprocessorDefinitions" );
  400. char *str = (char *)_alloca( Q_strlen( defines.String() ) + 1 );
  401. Assert( str );
  402. Q_strcpy( str, defines.String() );
  403. // now tokenize the string on the ";" char
  404. char *delim = strchr( str, ';' );
  405. char *curpos = str;
  406. while ( delim )
  407. {
  408. *delim = 0;
  409. delim++;
  410. if ( Q_stricmp( curpos, "WIN32" ) && Q_stricmp( curpos, "_WIN32" ) &&
  411. Q_stricmp( curpos, "_WINDOWS") && Q_stricmp( curpos, "WINDOWS")) // don't add WIN32 defines
  412. {
  413. config.AddDefine( curpos );
  414. }
  415. curpos = delim;
  416. delim = strchr( delim, ';' );
  417. }
  418. if ( Q_stricmp( curpos, "WIN32" ) && Q_stricmp( curpos, "_WIN32" ) &&
  419. Q_stricmp( curpos, "_WINDOWS") && Q_stricmp( curpos, "WINDOWS")) // don't add WIN32 defines
  420. {
  421. config.AddDefine( curpos );
  422. }
  423. CUtlSymbol includes = GetXMLAttribValue( pElem, "AdditionalIncludeDirectories" );
  424. char *str2 = (char *)_alloca( Q_strlen( includes.String() ) + 1 );
  425. Assert( str2 );
  426. Q_strcpy( str2, includes.String() );
  427. // now tokenize the string on the ";" char
  428. delim = strchr( str2, ',' );
  429. curpos = str2;
  430. while ( delim )
  431. {
  432. *delim = 0;
  433. delim++;
  434. config.AddInclude( curpos );
  435. curpos = delim;
  436. delim = strchr( delim, ',' );
  437. }
  438. config.AddInclude( curpos );
  439. }
  440. }
  441. }
  442. }
  443. #elif _LINUX
  444. DOMNodeList *nodes= pDoc->getElementsByTagName( _bstr_t("Tool"));
  445. if (nodes)
  446. {
  447. int len = nodes->getLength();
  448. for ( int i=0; i<len; i++ )
  449. {
  450. DOMNode *node = nodes->item(i);
  451. if (node)
  452. {
  453. CUtlSymbol toolName = GetXMLAttribValue( node, "Name" );
  454. if ( toolName == "VCCLCompilerTool" )
  455. {
  456. CUtlSymbol defines = GetXMLAttribValue( node, "PreprocessorDefinitions" );
  457. char *str = (char *)_alloca( Q_strlen( defines.String() ) + 1 );
  458. Assert( str );
  459. Q_strcpy( str, defines.String() );
  460. // now tokenize the string on the ";" char
  461. char *delim = strchr( str, ';' );
  462. char *curpos = str;
  463. while ( delim )
  464. {
  465. *delim = 0;
  466. delim++;
  467. if ( Q_stricmp( curpos, "WIN32" ) && Q_stricmp( curpos, "_WIN32" ) &&
  468. Q_stricmp( curpos, "_WINDOWS") && Q_stricmp( curpos, "WINDOWS")) // don't add WIN32 defines
  469. {
  470. config.AddDefine( curpos );
  471. }
  472. curpos = delim;
  473. delim = strchr( delim, ';' );
  474. }
  475. if ( Q_stricmp( curpos, "WIN32" ) && Q_stricmp( curpos, "_WIN32" ) &&
  476. Q_stricmp( curpos, "_WINDOWS") && Q_stricmp( curpos, "WINDOWS")) // don't add WIN32 defines
  477. {
  478. config.AddDefine( curpos );
  479. }
  480. CUtlSymbol includes = GetXMLAttribValue( node, "AdditionalIncludeDirectories" );
  481. char *str2 = (char *)_alloca( Q_strlen( includes.String() ) + 1 );
  482. Assert( str2 );
  483. Q_strcpy( str2, includes.String() );
  484. // now tokenize the string on the ";" char
  485. char token = ',';
  486. delim = strchr( str2, token );
  487. if ( !delim )
  488. {
  489. token = ';';
  490. delim = strchr( str2, token );
  491. }
  492. curpos = str2;
  493. while ( delim )
  494. {
  495. *delim = 0;
  496. delim++;
  497. Q_FixSlashes( curpos );
  498. char fullPath[ MAX_PATH ];
  499. Q_snprintf( fullPath, sizeof(fullPath), "%s/%s", m_BaseDir.String(), curpos );
  500. Q_StripTrailingSlash( fullPath );
  501. config.AddInclude( fullPath );
  502. curpos = delim;
  503. delim = strchr( delim, token );
  504. }
  505. Q_FixSlashes( curpos );
  506. Q_strlower( curpos );
  507. char fullPath[ MAX_PATH ];
  508. Q_snprintf( fullPath, sizeof(fullPath), "%s/%s", m_BaseDir.String(), curpos );
  509. Q_StripTrailingSlash( fullPath );
  510. config.AddInclude( fullPath );
  511. }
  512. }
  513. }
  514. }
  515. #endif
  516. return true;
  517. }
  518. //-----------------------------------------------------------------------------
  519. // Purpose: walks a particular files config entry and removes an files not valid for this config
  520. //-----------------------------------------------------------------------------
  521. bool CVCProjConvert::IterateFileConfigurations( IXMLDOMElement *pFile, CUtlSymbol fileName )
  522. {
  523. #ifdef _WIN32
  524. CComPtr<IXMLDOMNodeList> pConfigs;
  525. pFile->getElementsByTagName( _bstr_t("FileConfiguration"), &pConfigs);
  526. if (pConfigs)
  527. {
  528. long len = 0;
  529. pConfigs->get_length(&len);
  530. for ( int i=0; i<len; i++ )
  531. {
  532. CComPtr<IXMLDOMNode> pNode;
  533. pConfigs->get_item( i, &pNode);
  534. if (pNode)
  535. {
  536. CComQIPtr<IXMLDOMElement> pElem( pNode );
  537. CUtlSymbol configName = GetXMLAttribValue( pElem, "Name");
  538. CUtlSymbol excluded = GetXMLAttribValue( pElem ,"ExcludedFromBuild");
  539. if ( configName.IsValid() && excluded.IsValid() )
  540. {
  541. int index = FindConfiguration( configName );
  542. if ( index > 0 && excluded == "TRUE" )
  543. {
  544. m_Configurations[index].RemoveFile( fileName );
  545. }
  546. }
  547. }
  548. }//for
  549. }//if
  550. #elif _LINUX
  551. DOMNodeList *nodes = pFile->getElementsByTagName( _bstr_t("FileConfiguration"));
  552. if (nodes)
  553. {
  554. int len = nodes->getLength();
  555. for ( int i=0; i<len; i++ )
  556. {
  557. DOMNode *node = nodes->item(i);
  558. if (node)
  559. {
  560. CUtlSymbol configName = GetXMLAttribValue( node, "Name");
  561. CUtlSymbol excluded = GetXMLAttribValue( node ,"ExcludedFromBuild");
  562. if ( configName.IsValid() && excluded.IsValid() )
  563. {
  564. int index = FindConfiguration( configName );
  565. if ( index >= 0 && excluded == "TRUE" )
  566. {
  567. m_Configurations[index].RemoveFile( fileName );
  568. }
  569. }
  570. }
  571. }//for
  572. }//if
  573. #endif
  574. return true;
  575. }
  576. //-----------------------------------------------------------------------------
  577. // Purpose: walks the file elements in the vcproj and inserts them into configs
  578. //-----------------------------------------------------------------------------
  579. bool CVCProjConvert::ExtractFiles( IXMLDOMDocument *pDoc )
  580. {
  581. if (!pDoc)
  582. {
  583. return false;
  584. }
  585. Assert( m_Configurations.Count() ); // some configs must be loaded first
  586. #ifdef _WIN32
  587. CComPtr<IXMLDOMNodeList> pFiles;
  588. pDoc->getElementsByTagName( _bstr_t("File"), &pFiles);
  589. if (pFiles)
  590. {
  591. long len = 0;
  592. pFiles->get_length(&len);
  593. for ( int i=0; i<len; i++ )
  594. {
  595. CComPtr<IXMLDOMNode> pNode;
  596. pFiles->get_item( i, &pNode);
  597. if (pNode)
  598. {
  599. CComQIPtr<IXMLDOMElement> pElem( pNode );
  600. CUtlSymbol fileName = GetXMLAttribValue(pElem,"RelativePath");
  601. if ( fileName.IsValid() )
  602. {
  603. CConfiguration::FileType_e type = GetFileType( fileName.String() );
  604. CConfiguration::CFileEntry fileEntry( fileName.String(), type );
  605. for ( int i = 0; i < m_Configurations.Count(); i++ ) // add the file to all configs
  606. {
  607. CConfiguration & config = m_Configurations[i];
  608. config.InsertFile( fileEntry );
  609. }
  610. IterateFileConfigurations( pElem, fileName ); // now remove the excluded ones
  611. }
  612. }
  613. }//for
  614. }
  615. #elif _LINUX
  616. DOMNodeList *nodes = pDoc->getElementsByTagName( _bstr_t("File") );
  617. if (nodes)
  618. {
  619. int len = nodes->getLength();
  620. for ( int i=0; i<len; i++ )
  621. {
  622. DOMNode *node = nodes->item(i);
  623. if (node)
  624. {
  625. CUtlSymbol fileName = GetXMLAttribValue(node,"RelativePath");
  626. if ( fileName.IsValid() )
  627. {
  628. char fixedFileName[ MAX_PATH ];
  629. Q_strncpy( fixedFileName, fileName.String(), sizeof(fixedFileName) );
  630. if ( fixedFileName[0] == '.' && fixedFileName[1] == '\\' )
  631. {
  632. Q_memmove( fixedFileName, fixedFileName+2, sizeof(fixedFileName)-2 );
  633. }
  634. Q_FixSlashes( fixedFileName );
  635. FindFileCaseInsensitive( fixedFileName, sizeof(fixedFileName) );
  636. CConfiguration::FileType_e type = GetFileType( fileName.String() );
  637. CConfiguration::CFileEntry fileEntry( fixedFileName, type );
  638. for ( int i = 0; i < m_Configurations.Count(); i++ ) // add the file to all configs
  639. {
  640. CConfiguration & config = m_Configurations[i];
  641. config.InsertFile( fileEntry );
  642. }
  643. IterateFileConfigurations( node, fixedFileName ); // now remove the excluded ones
  644. }
  645. }
  646. }//for
  647. }
  648. #endif
  649. return true;
  650. }
  651. #ifdef _LINUX
  652. static char fileName[MAX_PATH];
  653. int CheckName(const struct dirent *dir)
  654. {
  655. return !strcasecmp( dir->d_name, fileName );
  656. }
  657. const char *findFileInDirCaseInsensitive(const char *file)
  658. {
  659. const char *dirSep = strrchr(file,'/');
  660. if( !dirSep )
  661. {
  662. dirSep=strrchr(file,'\\');
  663. if( !dirSep )
  664. {
  665. return NULL;
  666. }
  667. }
  668. char *dirName = static_cast<char *>( alloca( ( dirSep - file ) +1 ) );
  669. if( !dirName )
  670. return NULL;
  671. Q_strncpy( dirName, file, dirSep - file );
  672. dirName[ dirSep - file ] = '\0';
  673. struct dirent **namelist;
  674. int n;
  675. Q_strncpy( fileName, dirSep + 1, MAX_PATH );
  676. n = scandir( dirName , &namelist, CheckName, alphasort );
  677. if( n > 0 )
  678. {
  679. while( n > 1 )
  680. {
  681. free( namelist[n] ); // free the malloc'd strings
  682. n--;
  683. }
  684. Q_snprintf( fileName, sizeof( fileName ), "%s/%s", dirName, namelist[0]->d_name );
  685. return fileName;
  686. }
  687. else
  688. {
  689. // last ditch attempt, just return the lower case version!
  690. Q_strncpy( fileName, file, sizeof(fileName) );
  691. Q_strlower( fileName );
  692. return fileName;
  693. }
  694. }
  695. #endif
  696. void CVCProjConvert::FindFileCaseInsensitive( char *fileName, int fileNameSize )
  697. {
  698. char filePath[ MAX_PATH ];
  699. Q_snprintf( filePath, sizeof(filePath), "%s/%s", m_BaseDir.String(), fileName );
  700. struct _stat buf;
  701. if ( _stat( filePath, &buf ) == 0)
  702. {
  703. return; // found the filename directly
  704. }
  705. #ifdef _LINUX
  706. const char *realName = findFileInDirCaseInsensitive( filePath );
  707. if ( realName )
  708. {
  709. Q_strncpy( fileName, realName+strlen(m_BaseDir.String())+1, fileNameSize );
  710. }
  711. #endif
  712. }
  713. //-----------------------------------------------------------------------------
  714. // Purpose: extracts the generic type of a file being loaded
  715. //-----------------------------------------------------------------------------
  716. CVCProjConvert::CConfiguration::FileType_e CVCProjConvert::GetFileType( const char *fileName )
  717. {
  718. CConfiguration::FileType_e type = CConfiguration::FILE_TYPE_UNKNOWN_E;
  719. char ext[10];
  720. Q_ExtractFileExtension( fileName, ext, sizeof(ext) );
  721. if ( !Q_stricmp( ext, "lib" ) )
  722. {
  723. type = CConfiguration::FILE_LIBRARY;
  724. }
  725. else if ( !Q_stricmp( ext, "h" ) )
  726. {
  727. type = CConfiguration::FILE_HEADER;
  728. }
  729. else if ( !Q_stricmp( ext, "hh" ) )
  730. {
  731. type = CConfiguration::FILE_HEADER;
  732. }
  733. else if ( !Q_stricmp( ext, "hpp" ) )
  734. {
  735. type = CConfiguration::FILE_HEADER;
  736. }
  737. else if ( !Q_stricmp( ext, "cpp" ) )
  738. {
  739. type = CConfiguration::FILE_SOURCE;
  740. }
  741. else if ( !Q_stricmp( ext, "c" ) )
  742. {
  743. type = CConfiguration::FILE_SOURCE;
  744. }
  745. else if ( !Q_stricmp( ext, "cc" ) )
  746. {
  747. type = CConfiguration::FILE_SOURCE;
  748. }
  749. return type;
  750. }