csgo-2018-source/utils/vpc/groupscript.cpp

361 lines
9.4 KiB
C++
Raw Permalink Normal View History

2021-07-25 12:11:47 +08:00
//========= Copyright <20> 1996-2006, Valve Corporation, All rights reserved. ============//
//
// Purpose: VPC
//
//=====================================================================================//
#include "vpc.h"
//-----------------------------------------------------------------------------
// VPC_Group_FindOrCreateProject
//
//-----------------------------------------------------------------------------
projectIndex_t VPC_Group_FindOrCreateProject( const char *pName, bool bCreate )
{
for ( int i = 0; i < g_pVPC->m_Projects.Count(); i++ )
{
if ( !V_stricmp( pName, g_pVPC->m_Projects[i].name.String() ) )
{
return i;
}
}
if ( !bCreate )
return INVALID_INDEX;
int index = g_pVPC->m_Projects.AddToTail();
g_pVPC->m_Projects[index].name = pName;
return index;
}
//-----------------------------------------------------------------------------
// VPC_Group_CreateGroup
//
//-----------------------------------------------------------------------------
groupIndex_t VPC_Group_CreateGroup()
{
groupIndex_t index = g_pVPC->m_Groups.AddToTail();
return index;
}
//-----------------------------------------------------------------------------
// VPC_Group_FindOrCreateGroupTag
//
//-----------------------------------------------------------------------------
groupTagIndex_t VPC_Group_FindOrCreateGroupTag( const char *pName, bool bCreate )
{
for (int i=0; i<g_pVPC->m_GroupTags.Count(); i++)
{
if ( !V_stricmp( pName, g_pVPC->m_GroupTags[i].name.String() ) )
return i;
}
if ( !bCreate )
return INVALID_INDEX;
groupTagIndex_t index = g_pVPC->m_GroupTags.AddToTail();
g_pVPC->m_GroupTags[index].name = pName;
return index;
}
//-----------------------------------------------------------------------------
// VPC_GroupKeyword_Games
//
//-----------------------------------------------------------------------------
void VPC_GroupKeyword_Games()
{
const char *pToken;
pToken = g_pVPC->GetScript().GetToken( true );
if ( !pToken || !pToken[0] || V_stricmp( pToken, "{" ) )
g_pVPC->VPCSyntaxError();
while ( 1 )
{
pToken = g_pVPC->GetScript().GetToken( true );
if ( !pToken || !pToken[0] )
g_pVPC->VPCSyntaxError();
if ( !V_stricmp( pToken, "}" ) )
{
// end of section
break;
}
else
{
g_pVPC->FindOrCreateConditional( pToken, true, CONDITIONAL_GAME );
}
}
}
//-----------------------------------------------------------------------------
// VPC_GroupKeyword_Group
//
//-----------------------------------------------------------------------------
void VPC_GroupKeyword_Group()
{
const char *pToken;
bool bFirstToken = true;
groupIndex_t groupIndex;
projectIndex_t projectIndex;
groupIndex = VPC_Group_CreateGroup();
while ( 1 )
{
if ( !bFirstToken )
{
pToken = g_pVPC->GetScript().PeekNextToken( false );
if ( !pToken || !pToken[0] )
break;
}
else
{
bFirstToken = false;
}
pToken = g_pVPC->GetScript().GetToken( false );
if ( !pToken || !pToken[0] )
g_pVPC->VPCSyntaxError();
// specified tag now builds this group
groupTagIndex_t groupTagIndex = VPC_Group_FindOrCreateGroupTag( pToken, true );
g_pVPC->m_GroupTags[groupTagIndex].groups.AddToTail( groupIndex );
}
pToken = g_pVPC->GetScript().GetToken( true );
if ( !pToken || !pToken[0] || V_stricmp( pToken, "{" ) )
g_pVPC->VPCSyntaxError();
while ( 1 )
{
pToken = g_pVPC->GetScript().GetToken( true );
if ( !pToken || !pToken[0] )
g_pVPC->VPCSyntaxError();
if ( !V_stricmp( pToken, "}" ) )
{
// end of section
break;
}
else
{
projectIndex = VPC_Group_FindOrCreateProject( pToken, false );
if ( projectIndex != INVALID_INDEX )
{
int index = g_pVPC->m_Groups[groupIndex].projects.AddToTail();
g_pVPC->m_Groups[groupIndex].projects[index] = projectIndex;
}
else
{
g_pVPC->VPCWarning( "No Project %s defined, ignoring.", pToken );
continue;
}
}
}
}
//-----------------------------------------------------------------------------
// VPC_GroupKeyword_Project
//
//-----------------------------------------------------------------------------
void VPC_GroupKeyword_Project()
{
const char *pToken;
pToken = g_pVPC->GetScript().GetToken( false );
if ( !pToken || !pToken[0] )
g_pVPC->VPCSyntaxError();
if ( VPC_Group_FindOrCreateProject( pToken, false ) != INVALID_INDEX )
{
// already defined
g_pVPC->VPCWarning( "project %s already defined", pToken );
g_pVPC->VPCSyntaxError();
}
projectIndex_t projectIndex = VPC_Group_FindOrCreateProject( pToken, true );
// create a default group that contains just this project
groupIndex_t groupIndex = VPC_Group_CreateGroup();
g_pVPC->m_Groups[groupIndex].projects.AddToTail( projectIndex );
// create a default tag that matches the project name
groupTagIndex_t groupTagIndex = VPC_Group_FindOrCreateGroupTag( pToken, true );
g_pVPC->m_GroupTags[groupTagIndex].groups.AddToTail( groupIndex );
g_pVPC->m_GroupTags[groupTagIndex].bSameAsProject = true;
pToken = g_pVPC->GetScript().GetToken( true );
if ( !pToken || !pToken[0] || V_stricmp( pToken, "{" ) )
g_pVPC->VPCSyntaxError();
while ( 1 )
{
pToken = g_pVPC->GetScript().GetToken( true );
if ( !pToken || !pToken[0] )
g_pVPC->VPCSyntaxError();
if ( !V_stricmp( pToken, "}" ) )
{
// end of section
break;
}
else
{
scriptIndex_t scriptIndex = g_pVPC->m_Projects[projectIndex].scripts.AddToTail();
g_pVPC->m_Projects[projectIndex].scripts[scriptIndex].name = pToken;
pToken = g_pVPC->GetScript().PeekNextToken( false );
if ( pToken && pToken[0] )
{
pToken = g_pVPC->GetScript().GetToken( false );
g_pVPC->m_Projects[projectIndex].scripts[scriptIndex].m_condition = pToken;
}
}
}
}
//-----------------------------------------------------------------------------
// VPC_ParseGroupScript
//
//-----------------------------------------------------------------------------
void VPC_ParseGroupScript( const char *pScriptName )
{
char szScriptName[MAX_PATH];
const char *pToken;
// caller's pointer is aliased
strcpy( szScriptName, pScriptName );
V_FixSlashes( szScriptName );
g_pVPC->VPCStatus( false, "Parsing: %s", szScriptName );
g_pVPC->GetScript().PushScript( szScriptName );
while ( 1 )
{
pToken = g_pVPC->GetScript().GetToken( true );
if ( !pToken || !pToken[0] )
{
// end of file
break;
}
if ( !V_stricmp( pToken, "$include" ) )
{
pToken = g_pVPC->GetScript().GetToken( false );
if ( !pToken || !pToken[0] )
{
// end of file
g_pVPC->VPCSyntaxError();
}
// recurse into and run
VPC_ParseGroupScript( pToken );
}
else if ( !V_stricmp( pToken, "$games" ) )
{
VPC_GroupKeyword_Games();
}
else if ( !V_stricmp( pToken, "$group" ) )
{
VPC_GroupKeyword_Group();
}
else if ( !V_stricmp( pToken, "$project" ) )
{
VPC_GroupKeyword_Project();
}
else
{
g_pVPC->VPCSyntaxError();
}
}
g_pVPC->GetScript().PopScript();
}
//-----------------------------------------------------------------------------
// Collect all the +XXX, remove all the -XXX
// This allows removal to be the expected trumping operation.
//-----------------------------------------------------------------------------
void CVPC::GenerateBuildSet( CProjectDependencyGraph &dependencyGraph )
{
// process +XXX commands
for ( int i = 0; i < m_BuildCommands.Count(); i++ )
{
const char *pCommand = m_BuildCommands[i].Get();
if ( pCommand[0] == '-' )
continue;
groupTagIndex_t groupTagIndex = VPC_Group_FindOrCreateGroupTag( pCommand+1, false );
if ( groupTagIndex == INVALID_INDEX )
continue;
groupTag_t *pGroupTag = &g_pVPC->m_GroupTags[groupTagIndex];
CUtlVector<projectIndex_t> projectsToAdd;
for ( int j=0; j<pGroupTag->groups.Count(); j++ )
{
group_t *pGroup = &g_pVPC->m_Groups[pGroupTag->groups[j]];
for ( int k=0; k<pGroup->projects.Count(); k++ )
{
projectIndex_t targetProject = pGroup->projects[k];
if ( pCommand[0] == '*' )
{
// Add this project and any projects that depend on it.
if ( !dependencyGraph.HasGeneratedDependencies() )
dependencyGraph.BuildProjectDependencies( BUILDPROJDEPS_CHECK_ALL_PROJECTS );
dependencyGraph.GetProjectDependencyTree( targetProject, projectsToAdd, false );
}
else if ( pCommand[0] == '@' )
{
// Add this project and any projects that it depends on.
if ( !dependencyGraph.HasGeneratedDependencies() )
dependencyGraph.BuildProjectDependencies( BUILDPROJDEPS_CHECK_ALL_PROJECTS );
dependencyGraph.GetProjectDependencyTree( targetProject, projectsToAdd, true );
}
else
{
projectsToAdd.AddToTail( targetProject );
}
}
}
// Add all the projects in the list.
for ( int j=0; j < projectsToAdd.Count(); j++ )
{
projectIndex_t targetProject = projectsToAdd[j];
if ( g_pVPC->m_TargetProjects.Find( targetProject ) == -1 )
{
g_pVPC->m_TargetProjects.AddToTail( targetProject );
}
}
}
// process -XXX commands, explicitly remove tagge projects
for ( int i=0; i<m_BuildCommands.Count(); i++ )
{
const char *pCommand = m_BuildCommands[i].Get();
if ( pCommand[0] == '+' || pCommand[0] == '*' || pCommand[0] == '@' )
continue;
groupTagIndex_t groupTagIndex = VPC_Group_FindOrCreateGroupTag( pCommand+1, false );
if ( groupTagIndex == INVALID_INDEX )
continue;
groupTag_t *pGroupTag = &g_pVPC->m_GroupTags[groupTagIndex];
for ( int j=0; j<pGroupTag->groups.Count(); j++ )
{
group_t *pGroup = &g_pVPC->m_Groups[pGroupTag->groups[j]];
for ( int k=0; k<pGroup->projects.Count(); k++ )
{
g_pVPC->m_TargetProjects.FindAndRemove( pGroup->projects[k] );
}
}
}
}