NOXREF void TextMessageParse(unsigned char *pMemFile, int fileSize) { NOXREFCHECK; char buf[512]; char trim[512]; char *pCurrentText; char *pNameHeap; char currentName[512]; char nameHeap[NAME_HEAP_SIZE]; int lastNamePos; int mode; int lineNumber; int filePos; int lastLinePos; int messageCount; client_textmessage_t textMessages[MAX_MESSAGES]; int i; int nameHeapSize; int textHeapSize; int messageSize; int nameOffset; lastNamePos = 0; lineNumber = 0; filePos = 0; lastLinePos = 0; messageCount = 0; mode = MSGFILE_NAME; while (memfgets(pMemFile, fileSize, &filePos, buf, 512) != NULL) { if(messageCount >= MAX_MESSAGES) Sys_Error("%s: messageCount >= MAX_MESSAGES", __func__); TrimSpace(buf, trim); switch (mode) { case MSGFILE_NAME: { if (IsComment(trim)) break; if (ParseDirective(trim)) break; if (IsStartOfText(trim)) { mode = MSGFILE_TEXT; pCurrentText = (char *)(pMemFile + filePos); break; } if (IsEndOfText(trim)) { Con_DPrintf("Unexpected '}' found, line %d\n", lineNumber); return; } Q_strncpy(currentName, trim, 511); currentName[511] = 0; break; } case MSGFILE_TEXT: { if (IsEndOfText(trim)) { int length = Q_strlen(currentName); if (lastNamePos + length > sizeof(nameHeap)) { Con_DPrintf("Error parsing file! length > %i bytes\n", sizeof(nameHeap)); return; } Q_strcpy(nameHeap + lastNamePos, currentName); pMemFile[lastLinePos - 1] = 0; textMessages[messageCount] = gMessageParms; textMessages[messageCount].pName = nameHeap + lastNamePos; lastNamePos += Q_strlen(currentName) + 1; textMessages[messageCount].pMessage = pCurrentText; messageCount++; mode = MSGFILE_NAME; break; } if (IsStartOfText(trim)) { Con_DPrintf("Unexpected '{' found, line %d\n", lineNumber); return; } break; } } lineNumber++; lastLinePos = filePos; } Con_DPrintf("Parsed %d text messages\n", messageCount); nameHeapSize = lastNamePos; textHeapSize = 0; for (i = 0; i < messageCount; i++) textHeapSize += Q_strlen(textMessages[i].pMessage) + 1; messageSize = (messageCount * sizeof(client_textmessage_t)); gMessageTable = (client_textmessage_t *)Mem_Malloc(textHeapSize + nameHeapSize + messageSize); Q_memcpy(gMessageTable, textMessages, messageSize); pNameHeap = ((char *)gMessageTable) + messageSize; Q_memcpy(pNameHeap, nameHeap, nameHeapSize); nameOffset = pNameHeap - gMessageTable[0].pName; pCurrentText = pNameHeap + nameHeapSize; for (i = 0; i < messageCount; i++) { gMessageTable[i].pName += nameOffset; Q_strcpy(pCurrentText, gMessageTable[i].pMessage); gMessageTable[i].pMessage = pCurrentText; pCurrentText += Q_strlen(pCurrentText) + 1; } gMessageTableCount = messageCount; }
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; }