static void InitializeCharacterSets() { static bool s_CharacterSetInitialized = false; if (!s_CharacterSetInitialized) { CharacterSetBuild( &g_BreakSet, "{}()'" ); CharacterSetBuild( &g_BreakSetIncludingColons, "{}()':" ); s_CharacterSetInitialized = true; } }
CCommand::CCommand() { if(!s_bBuiltBreakSet) { s_bBuiltBreakSet = true; CharacterSetBuild(&s_BreakSet, "{}()':"); } Reset(); }
CCommand::CCommand( int nArgC, const char **ppArgV ) { Assert( nArgC > 0 ); if ( !s_bBuiltBreakSet ) { s_bBuiltBreakSet = true; CharacterSetBuild( &s_BreakSet, "{}()':" ); } Reset(); char *pBuf = m_pArgvBuffer; char *pSBuf = m_pArgSBuffer; m_nArgc = nArgC; for ( int i = 0; i < nArgC; ++i ) { m_ppArgv[i] = pBuf; int nLen = Q_strlen( ppArgV[i] ); memcpy( pBuf, ppArgV[i], nLen+1 ); if ( i == 0 ) { m_nArgv0Size = nLen; } pBuf += nLen+1; bool bContainsSpace = strchr( ppArgV[i], ' ' ) != NULL; if ( bContainsSpace ) { *pSBuf++ = '\"'; } memcpy( pSBuf, ppArgV[i], nLen ); pSBuf += nLen; if ( bContainsSpace ) { *pSBuf++ = '\"'; } if ( i != nArgC - 1 ) { *pSBuf++ = ' '; } } }
//----------------------------------------------------------------------------- // Generate a tree containing files from a reslist. Returns TRUE if successful. //----------------------------------------------------------------------------- bool LoadReslist( const char *pReslistName, CUtlRBTree< CUtlString, int > *pTree ) { CUtlBuffer buffer; if ( !scriptlib->ReadFileToBuffer( pReslistName, buffer, true ) ) { return false; } char szBasename[MAX_PATH]; V_FileBase( pReslistName, szBasename, sizeof( szBasename ) ); characterset_t breakSet; CharacterSetBuild( &breakSet, "" ); // parse reslist char szToken[MAX_PATH]; char szBspName[MAX_PATH]; szBspName[0] = '\0'; for ( ;; ) { int nTokenSize = buffer.ParseToken( &breakSet, szToken, sizeof( szToken ) ); if ( nTokenSize <= 0 ) { break; } // reslists are pc built, filenames can be sloppy V_strlower( szToken ); V_FixSlashes( szToken ); V_RemoveDotSlashes( szToken ); // can safely cull filetypes that are ignored by queued loader at runtime bool bKeep = false; const char *pExt = V_GetFileExtension( szToken ); if ( !pExt ) { // unknown continue; } else if ( !V_stricmp( pExt, "vmt" ) || !V_stricmp( pExt, "vhv" ) || !V_stricmp( pExt, "mdl" ) || !V_stricmp( pExt, "raw" ) || !V_stricmp( pExt, "wav" ) ) { bKeep = true; } else if ( !V_stricmp( pExt, "mp3" ) ) { // change to .wav V_SetExtension( szToken, ".wav", sizeof( szToken ) ); bKeep = true; } else if ( !V_stricmp( pExt, "bsp" ) ) { // reslists erroneously have multiple bsps if ( !V_stristr( szToken, szBasename ) ) { // wrong one, cull it continue; } else { // right one, save it strcpy( szBspName, szToken ); bKeep = true; } } if ( bKeep ) { FindOrAddFileToResourceList( szToken, pTree ); } } if ( !szBspName[0] ) { // reslist is not bsp derived, nothing more to do return true; } CUtlVector< CUtlString > bspList; bool bOK = GetDependants_BSP( szBspName, &bspList ); if ( !bOK ) { return false; } // add all the bsp dependants to the resource list for ( int i=0; i<bspList.Count(); i++ ) { FindOrAddFileToResourceList( bspList[i].String(), pTree ); } // iterate all the models in the resource list, get all their dependents CUtlVector< CUtlString > modelList; for ( int i = pTree->FirstInorder(); i != pTree->InvalidIndex(); i = pTree->NextInorder( i ) ) { const char *pExt = V_GetFileExtension( pTree->Element( i ).String() ); if ( !pExt || V_stricmp( pExt, "mdl" ) ) { continue; } if ( !GetDependants_MDL( pTree->Element( i ).String(), &modelList ) ) { return false; } } // add all the model dependents to the resource list for ( int i=0; i<modelList.Count(); i++ ) { FindOrAddFileToResourceList( modelList[i].String(), pTree ); } // check for optional commentary, include wav dependencies char szCommentaryName[MAX_PATH]; V_ComposeFileName( g_szGamePath, szBspName, szCommentaryName, sizeof( szCommentaryName ) ); V_StripExtension( szCommentaryName, szCommentaryName, sizeof( szCommentaryName ) ); V_strncat( szCommentaryName, "_commentary.txt", sizeof( szCommentaryName ) ); CUtlBuffer commentaryBuffer; if ( ReadFileToBuffer( szCommentaryName, commentaryBuffer, true, true ) ) { // any single token may be quite large to due to text char szCommentaryToken[8192]; for ( ;; ) { int nTokenSize = commentaryBuffer.ParseToken( &breakSet, szCommentaryToken, sizeof( szCommentaryToken ) ); if ( nTokenSize < 0 ) { break; } if ( nTokenSize > 0 && !V_stricmp( szCommentaryToken, "commentaryfile" ) ) { // get the commentary file nTokenSize = commentaryBuffer.ParseToken( &breakSet, szCommentaryToken, sizeof( szCommentaryToken ) ); if ( nTokenSize > 0 ) { // skip past sound chars char *pName = szCommentaryToken; while ( *pName && IsSoundChar( *pName ) ) { pName++; } char szWavFile[MAX_PATH]; V_snprintf( szWavFile, sizeof( szWavFile ), "sound/%s", pName ); FindOrAddFileToResourceList( szWavFile, pTree ); } } } } // check for optional blacklist char szBlacklist[MAX_PATH]; V_ComposeFileName( g_szGamePath, "reslistfixes_xbox.xsc", szBlacklist, sizeof( szBlacklist ) ); CUtlBuffer blacklistBuffer; if ( ReadFileToBuffer( szBlacklist, blacklistBuffer, true, true ) ) { for ( ;; ) { int nTokenSize = blacklistBuffer.ParseToken( &breakSet, szToken, sizeof( szToken ) ); if ( nTokenSize <= 0 ) { break; } bool bAdd; if ( !V_stricmp( szToken, "-" ) ) { bAdd = false; } else if ( !V_stricmp( szToken, "+" ) ) { bAdd = true; } else { // bad syntax, skip line Msg( "Bad Syntax, expecting '+' or '-' as first token in reslist fixup file '%s'.\n", szBlacklist ); continue; } // get entry nTokenSize = blacklistBuffer.ParseToken( &breakSet, szToken, sizeof( szToken ) ); if ( nTokenSize <= 0 ) { break; } if ( bAdd ) { FindOrAddFileToResourceList( szToken, pTree ); } else { RemoveFileFromResourceList( szToken, pTree ); } } } return true; }
void TextMessageParse( byte *pMemFile, int fileSize ) { char buf[512], trim[512]; char *pCurrentText=0, *pNameHeap; char currentName[512], nameHeap[ NAME_HEAP_SIZE ]; int lastNamePos; int mode = MSGFILE_NAME; // Searching for a message name int lineNumber, filePos, lastLinePos; int messageCount; client_textmessage_t textMessages[ MAX_MESSAGES ]; int i, nameHeapSize, textHeapSize, messageSize, nameOffset; lastNamePos = 0; lineNumber = 0; filePos = 0; lastLinePos = 0; messageCount = 0; CharacterSetBuild( &g_WhiteSpace, " \r\n\t" ); while( memfgets( pMemFile, fileSize, &filePos, buf, 512 ) != NULL ) { if(messageCount>=MAX_MESSAGES) { Sys_Error("tmessage::TextMessageParse : messageCount>=MAX_MESSAGES"); } TrimSpace( buf, trim ); switch( mode ) { case MSGFILE_NAME: if ( IsComment( trim ) ) // Skip comment lines break; if ( ParseDirective( trim ) ) // Is this a directive "$command"?, if so parse it and break break; if ( IsStartOfText( trim ) ) { mode = MSGFILE_TEXT; pCurrentText = (char*)(pMemFile + filePos); break; } if ( IsEndOfText( trim ) ) { Con_DPrintf("Unexpected '}' found, line %d\n", lineNumber ); return; } strcpy( currentName, trim ); break; case MSGFILE_TEXT: if ( IsEndOfText( trim ) ) { int length = strlen(currentName); // Save name on name heap if ( lastNamePos + length > 8192 ) { Con_DPrintf("Error parsing file!\n" ); return; } strcpy( nameHeap + lastNamePos, currentName ); // Terminate text in-place in the memory file (it's temporary memory that will be deleted) pMemFile[ lastLinePos - 1 ] = 0; // Save name/text on heap textMessages[ messageCount ] = gMessageParms; textMessages[ messageCount ].pName = nameHeap + lastNamePos; lastNamePos += strlen(currentName) + 1; textMessages[ messageCount ].pMessage = pCurrentText; messageCount++; // Reset parser to search for names mode = MSGFILE_NAME; break; } if ( IsStartOfText( trim ) ) { Con_DPrintf("Unexpected '{' found, line %d\n", lineNumber ); return; } break; } lineNumber++; lastLinePos = filePos; if ( messageCount >= MAX_MESSAGES ) { Con_Printf("WARNING: TOO MANY MESSAGES IN TITLES.TXT, MAX IS %d\n", MAX_MESSAGES ); break; } } Con_DPrintf("Parsed %d text messages\n", messageCount ); nameHeapSize = lastNamePos; textHeapSize = 0; for ( i = 0; i < messageCount; i++ ) textHeapSize += strlen( textMessages[i].pMessage ) + 1; messageSize = (messageCount * sizeof(client_textmessage_t)); // Must malloc because we need to be able to clear it after initialization gMessageTable = (client_textmessage_t *)malloc( textHeapSize + nameHeapSize + messageSize ); // Copy table over memcpy( gMessageTable, textMessages, messageSize ); // Copy Name heap pNameHeap = ((char *)gMessageTable) + messageSize; memcpy( pNameHeap, nameHeap, nameHeapSize ); nameOffset = pNameHeap - gMessageTable[0].pName; // Copy text & fixup pointers pCurrentText = pNameHeap + nameHeapSize; for ( i = 0; i < messageCount; i++ ) { gMessageTable[i].pName += nameOffset; // Adjust name pointer (parallel buffer) strcpy( pCurrentText, gMessageTable[i].pMessage ); // Copy text over gMessageTable[i].pMessage = pCurrentText; pCurrentText += strlen( pCurrentText ) + 1; } #if _DEBUG if ( (pCurrentText - (char *)gMessageTable) != (textHeapSize + nameHeapSize + messageSize) ) Con_Printf("Overflow text message buffer!!!!!\n"); #endif gMessageTableCount = messageCount; }