338 lines
9.0 KiB
C++
338 lines
9.0 KiB
C++
//====== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. =======
|
|
//
|
|
// Purpose:
|
|
//
|
|
//=============================================================================
|
|
|
|
#include "vpc.h"
|
|
#include "baseprojectdatacollector.h"
|
|
#include "tier1/utlstack.h"
|
|
#include "p4lib/ip4.h"
|
|
|
|
// ------------------------------------------------------------------------------------------------ //
|
|
// CSpecificConfig implementation.
|
|
// ------------------------------------------------------------------------------------------------ //
|
|
|
|
CSpecificConfig::CSpecificConfig( CSpecificConfig *pParentConfig )
|
|
: m_pParentConfig( pParentConfig )
|
|
{
|
|
m_pKV = new KeyValues( "" );
|
|
m_bFileExcluded = false;
|
|
m_bIsSchema = false;
|
|
}
|
|
|
|
CSpecificConfig::~CSpecificConfig()
|
|
{
|
|
m_pKV->deleteThis();
|
|
}
|
|
|
|
const char* CSpecificConfig::GetConfigName()
|
|
{
|
|
return m_pKV->GetName();
|
|
}
|
|
|
|
const char* CSpecificConfig::GetOption( const char *pOptionName )
|
|
{
|
|
const char *pRet = m_pKV->GetString( pOptionName, NULL );
|
|
if ( pRet )
|
|
return pRet;
|
|
|
|
if ( m_pParentConfig )
|
|
return m_pParentConfig->m_pKV->GetString( pOptionName, NULL );
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------ //
|
|
// CFileConfig implementation.
|
|
// ------------------------------------------------------------------------------------------------ //
|
|
|
|
CFileConfig::~CFileConfig()
|
|
{
|
|
Term();
|
|
}
|
|
|
|
void CFileConfig::Term()
|
|
{
|
|
m_Configurations.PurgeAndDeleteElements();
|
|
}
|
|
|
|
const char* CFileConfig::GetName()
|
|
{
|
|
return m_Filename.String();
|
|
}
|
|
|
|
CSpecificConfig* CFileConfig::GetConfig( const char *pConfigName )
|
|
{
|
|
int i = m_Configurations.Find( pConfigName );
|
|
if ( i == m_Configurations.InvalidIndex() )
|
|
return NULL;
|
|
else
|
|
return m_Configurations[i];
|
|
}
|
|
|
|
CSpecificConfig* CFileConfig::GetOrCreateConfig( const char *pConfigName, CSpecificConfig *pParentConfig )
|
|
{
|
|
int i = m_Configurations.Find( pConfigName );
|
|
if ( i == m_Configurations.InvalidIndex() )
|
|
{
|
|
CSpecificConfig *pConfig = new CSpecificConfig( pParentConfig );
|
|
i = m_Configurations.Insert( pConfigName, pConfig );
|
|
}
|
|
|
|
return m_Configurations[i];
|
|
}
|
|
|
|
bool CFileConfig::IsExcludedFrom( const char *pConfigName )
|
|
{
|
|
CSpecificConfig *pSpecificConfig = GetConfig( pConfigName );
|
|
if ( pSpecificConfig )
|
|
return pSpecificConfig->m_bFileExcluded;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------ //
|
|
// CBaseProjectDataCollector implementation.
|
|
// ------------------------------------------------------------------------------------------------ //
|
|
|
|
CBaseProjectDataCollector::CBaseProjectDataCollector( CRelevantPropertyNames *pNames ) : m_Files( k_eDictCompareTypeFilenames )
|
|
{
|
|
m_RelevantPropertyNames.m_nNames = 0;
|
|
m_RelevantPropertyNames.m_pNames = NULL;
|
|
|
|
if ( pNames )
|
|
{
|
|
m_RelevantPropertyNames = *pNames;
|
|
}
|
|
}
|
|
|
|
CBaseProjectDataCollector::~CBaseProjectDataCollector()
|
|
{
|
|
Term();
|
|
}
|
|
|
|
void CBaseProjectDataCollector::StartProject()
|
|
{
|
|
m_ProjectName = "UNNAMED";
|
|
m_CurFileConfig.Push( &m_BaseConfigData );
|
|
m_CurSpecificConfig.Push( NULL );
|
|
}
|
|
|
|
void CBaseProjectDataCollector::EndProject()
|
|
{
|
|
}
|
|
|
|
void CBaseProjectDataCollector::Term()
|
|
{
|
|
m_BaseConfigData.Term();
|
|
m_Files.PurgeAndDeleteElements();
|
|
m_CurFileConfig.Purge();
|
|
m_CurSpecificConfig.Purge();
|
|
}
|
|
|
|
CUtlString CBaseProjectDataCollector::GetProjectName()
|
|
{
|
|
return m_ProjectName;
|
|
}
|
|
|
|
void CBaseProjectDataCollector::SetProjectName( const char *pProjectName )
|
|
{
|
|
char tmpBuf[MAX_PATH];
|
|
V_strncpy( tmpBuf, pProjectName, sizeof( tmpBuf ) );
|
|
Q_strlower( tmpBuf );
|
|
m_ProjectName = tmpBuf;
|
|
}
|
|
|
|
// Get a list of all configurations.
|
|
void CBaseProjectDataCollector::GetAllConfigurationNames( CUtlVector< CUtlString > &configurationNames )
|
|
{
|
|
configurationNames.Purge();
|
|
for ( int i=m_BaseConfigData.m_Configurations.First(); i != m_BaseConfigData.m_Configurations.InvalidIndex(); i=m_BaseConfigData.m_Configurations.Next(i) )
|
|
{
|
|
configurationNames.AddToTail( m_BaseConfigData.m_Configurations.GetElementName(i) );
|
|
}
|
|
}
|
|
|
|
void CBaseProjectDataCollector::StartConfigurationBlock( const char *pConfigName, bool bFileSpecific )
|
|
{
|
|
CFileConfig *pFileConfig = m_CurFileConfig.Top();
|
|
|
|
// Find or add a new config block.
|
|
char sLowerCaseConfigName[MAX_PATH];
|
|
V_strncpy( sLowerCaseConfigName, pConfigName, sizeof( sLowerCaseConfigName ) );
|
|
V_strlower( sLowerCaseConfigName );
|
|
|
|
int index = pFileConfig->m_Configurations.Find( sLowerCaseConfigName );
|
|
if ( index == -1 )
|
|
{
|
|
CSpecificConfig *pParent = ( pFileConfig==&m_BaseConfigData ? NULL : m_BaseConfigData.GetOrCreateConfig( sLowerCaseConfigName, NULL ) );
|
|
|
|
CSpecificConfig *pConfig = new CSpecificConfig( pParent );
|
|
pConfig->m_bFileExcluded = false;
|
|
pConfig->m_pKV->SetName( sLowerCaseConfigName );
|
|
index = pFileConfig->m_Configurations.Insert( sLowerCaseConfigName, pConfig );
|
|
}
|
|
|
|
// Remember what the current config is.
|
|
m_CurSpecificConfig.Push( pFileConfig->m_Configurations[index] );
|
|
}
|
|
|
|
void CBaseProjectDataCollector::EndConfigurationBlock()
|
|
{
|
|
m_CurSpecificConfig.Pop();
|
|
}
|
|
|
|
bool CBaseProjectDataCollector::StartPropertySection( configKeyword_e keyword, bool *pbShouldSkip )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
void CBaseProjectDataCollector::HandleProperty( const char *pProperty, const char *pCustomScriptData )
|
|
{
|
|
int i;
|
|
for ( i=0; i < m_RelevantPropertyNames.m_nNames; i++ )
|
|
{
|
|
if ( V_stricmp( m_RelevantPropertyNames.m_pNames[i], pProperty ) == 0 )
|
|
break;
|
|
}
|
|
if ( i == m_RelevantPropertyNames.m_nNames )
|
|
{
|
|
// not found
|
|
return;
|
|
}
|
|
|
|
if ( pCustomScriptData )
|
|
{
|
|
g_pVPC->GetScript().PushScript( "HandleProperty( custom script data )", pCustomScriptData );
|
|
}
|
|
|
|
const char *pNextToken = g_pVPC->GetScript().PeekNextToken( false );
|
|
if ( pNextToken && pNextToken[0] != 0 )
|
|
{
|
|
// Pass in the previous value so the $base substitution works.
|
|
CSpecificConfig *pConfig = m_CurSpecificConfig.Top();
|
|
const char *pBaseString = pConfig->m_pKV->GetString( pProperty );
|
|
char buff[MAX_SYSTOKENCHARS];
|
|
if ( g_pVPC->GetScript().ParsePropertyValue( pBaseString, buff, sizeof( buff ) ) )
|
|
{
|
|
pConfig->m_pKV->SetString( pProperty, buff );
|
|
}
|
|
}
|
|
|
|
if ( pCustomScriptData )
|
|
{
|
|
// Restore prior script state
|
|
g_pVPC->GetScript().PopScript();
|
|
}
|
|
}
|
|
|
|
void CBaseProjectDataCollector::EndPropertySection( configKeyword_e keyword )
|
|
{
|
|
}
|
|
|
|
void CBaseProjectDataCollector::StartFolder( const char *pFolderName )
|
|
{
|
|
}
|
|
void CBaseProjectDataCollector::EndFolder()
|
|
{
|
|
}
|
|
|
|
bool CBaseProjectDataCollector::StartFile( const char *pFilename, bool bWarnIfAlreadyExists )
|
|
{
|
|
CFileConfig *pFileConfig = new CFileConfig;
|
|
pFileConfig->m_Filename = pFilename;
|
|
m_Files.Insert( pFilename, pFileConfig );
|
|
|
|
m_CurFileConfig.Push( pFileConfig );
|
|
m_CurSpecificConfig.Push( NULL );
|
|
|
|
char szFullPath[MAX_PATH];
|
|
|
|
V_GetCurrentDirectory( szFullPath, sizeof( szFullPath ) );
|
|
V_AppendSlash( szFullPath, sizeof( szFullPath ) );
|
|
V_strncat( szFullPath, pFilename, sizeof( szFullPath ) );
|
|
V_RemoveDotSlashes( szFullPath );
|
|
|
|
#if 0
|
|
// Add file to Perforce if it isn't there already
|
|
if ( Sys_Exists( szFullPath ) )
|
|
{
|
|
if ( m_bP4AutoAdd && p4 && !p4->IsFileInPerforce( szFullPath ) )
|
|
{
|
|
p4->OpenFileForAdd( szFullPath );
|
|
VPCStatus( "%s automatically opened for add in default changelist.", szFullPath );
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// g_pVPC->Warning( "%s not found on disk at location specified in project script.", szFullPath );
|
|
}
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
void CBaseProjectDataCollector::EndFile()
|
|
{
|
|
m_CurFileConfig.Pop();
|
|
m_CurSpecificConfig.Pop();
|
|
}
|
|
|
|
// This is actually just per-file configuration data.
|
|
void CBaseProjectDataCollector::FileExcludedFromBuild( bool bExcluded )
|
|
{
|
|
CSpecificConfig *pConfig = m_CurSpecificConfig.Top();
|
|
pConfig->m_bFileExcluded = bExcluded;
|
|
}
|
|
|
|
void CBaseProjectDataCollector::FileIsSchema( bool bIsSchema )
|
|
{
|
|
CSpecificConfig *pConfig = m_CurSpecificConfig.Top();
|
|
pConfig->m_bIsSchema = bIsSchema;
|
|
}
|
|
|
|
|
|
bool CBaseProjectDataCollector::RemoveFile( const char *pFilename )
|
|
{
|
|
bool bRet = false;
|
|
int i = m_Files.Find( pFilename );
|
|
if ( i != m_Files.InvalidIndex() )
|
|
{
|
|
delete m_Files[i];
|
|
m_Files.RemoveAt( i );
|
|
bRet = true;
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
void CBaseProjectDataCollector::DoStandardVisualStudioReplacements( const char *pStartString, const char *pFullInputFilename, char *pOut, int outLen )
|
|
{
|
|
// Decompose the input filename.
|
|
char sInputDir[MAX_PATH], sFileBase[MAX_PATH];
|
|
if ( !V_ExtractFilePath( pFullInputFilename, sInputDir, sizeof( sInputDir ) ) )
|
|
g_pVPC->VPCError( "V_ExtractFilePath failed on %s.", pFullInputFilename );
|
|
|
|
V_FileBase( pFullInputFilename, sFileBase, sizeof( sFileBase ) );
|
|
|
|
// Handle $(InputPath), $(InputDir), $(InputName)
|
|
char *strings[2] =
|
|
{
|
|
(char*)stackalloc( outLen ),
|
|
(char*)stackalloc( outLen )
|
|
};
|
|
|
|
V_StrSubst( pStartString, "$(InputPath)", pFullInputFilename, strings[0], outLen );
|
|
V_StrSubst( strings[0], "$(InputDir)", sInputDir, strings[1], outLen );
|
|
V_StrSubst( strings[1], "$(InputName)", sFileBase, strings[0], outLen );
|
|
V_StrSubst( strings[0], "$(IntDir)", "$(OBJ_DIR)", strings[1], outLen );
|
|
V_StrSubst( strings[1], "$(InputFileName)", pFullInputFilename + Q_strlen(sInputDir), strings[0], outLen );
|
|
|
|
V_strncpy( pOut, strings[0], outLen );
|
|
V_FixSlashes( pOut, '/' );
|
|
}
|