//========= Copyright © 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; im_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 projectsToAdd; for ( int j=0; jgroups.Count(); j++ ) { group_t *pGroup = &g_pVPC->m_Groups[pGroupTag->groups[j]]; for ( int k=0; kprojects.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; im_GroupTags[groupTagIndex]; for ( int j=0; jgroups.Count(); j++ ) { group_t *pGroup = &g_pVPC->m_Groups[pGroupTag->groups[j]]; for ( int k=0; kprojects.Count(); k++ ) { g_pVPC->m_TargetProjects.FindAndRemove( pGroup->projects[k] ); } } } }