From b405c1c84b4119aa7f4e1506802c64d9745cfd68 Mon Sep 17 00:00:00 2001
From: z64555 <z1281110@gmail.com>
Date: Tue, 20 May 2014 20:57:13 -0500
Subject: [PATCH] Fixes 3039: C++ stdlib was having data race issues with
 instanciating the debug_commands and the vector that was supposed to contain
 them. Seems like :v: ran into this issue a few times before...

---
 code/debugconsole/console.cpp     | 19 +++++-----
 code/debugconsole/console.h       |  5 +++
 code/debugconsole/consolecmds.cpp | 79 +++++++++++++++++++++++++++++----------
 3 files changed, 74 insertions(+), 29 deletions(-)

diff --git a/code/debugconsole/console.cpp b/code/debugconsole/console.cpp
index b7eb607..c7acecb 100644
--- a/code/debugconsole/console.cpp
+++ b/code/debugconsole/console.cpp
@@ -138,8 +138,9 @@ void dc_do_command(SCP_string *cmd_str)
 	 *      Call the function to process the command (the rest of the command line is in the parser)
 	 *          Function takes care of long_help and status depending on the mode.
 	 */
+	int i;
 	SCP_string command;
-	extern SCP_vector<debug_command*> dc_commands;	// z64: I don't like this extern here, at all. Nope nope nope.
+	extern debug_command* dc_commands[];	// z64: I don't like this extern here, at all. Nope nope nope.
 
 	if (cmd_str->empty()) {
 		return;
@@ -149,15 +150,20 @@ void dc_do_command(SCP_string *cmd_str)
 
 	dc_stuff_string_white(command);		// Grab the first token, presumably this is a command
 
-	SCP_vector<debug_command*>::iterator it = std::find_if(dc_commands.begin(), dc_commands.end(), is_dcmd(command.c_str()));
+	for (i = 0; i < dc_commands_size; ++i) {
+
+		if (stricmp(dc_commands[i]->name, command.c_str()) == 0) {
+			break;
+		} // Else, continue
+	}
 
-	if (it == dc_commands.end()) {
+	if (i == dc_commands_size) {
 		dc_printf("Command not found: '%s'\n", command.c_str());
 		return;
 	} // Else, we found our command
 
 	try {
-		(*it)->func();	// Run the command!
+		dc_commands[i]->func();	// Run the command!
 	
 	} catch (errParseString err) {
 		dc_printf("Require string(s) not found: \n");
@@ -267,17 +273,12 @@ void dc_draw_window(bool show_prompt)
 
 void dc_init(void)
 {
-	extern SCP_vector<debug_command*> dc_commands;
-
 	if (debug_inited) {
 		return;
 	}
 
 	debug_inited = TRUE;
 
-	// Sort debug_commands
-	std::sort(dc_commands.begin(), dc_commands.end(), dcmd_less);
-
 	// Init window settings
 	dc_font = FONT1;
 	row_height = ((Current_font->h) * 3) / 2;	// Row/Line height, in pixels
diff --git a/code/debugconsole/console.h b/code/debugconsole/console.h
index 867a979..c8abde1 100644
--- a/code/debugconsole/console.h
+++ b/code/debugconsole/console.h
@@ -22,6 +22,8 @@
 #include "globalincs/pstypes.h"
 #include "globalincs/vmallocator.h"
 
+#define DC_MAX_COMMANDS 300
+
 class debug_command;
 
 /**
@@ -222,6 +224,8 @@ public:
 	const char *help;		//!< The short help string, as shown by 'help <command>'
 	void (*func)();	//!< Pointer to the function that to run when this command is evoked
 
+	debug_command();
+
 	/**
 	* @brief Adds a debug command to the debug_commands map, if it isn't in there already.
 	*
@@ -248,6 +252,7 @@ public:
 };
 
 extern bool Dc_debug_on;
+extern int dc_commands_size;
 extern uint lastline;
 extern SCP_string dc_command_str;	// The rest of the command line, from the end of the last processed arg on.
 
diff --git a/code/debugconsole/consolecmds.cpp b/code/debugconsole/consolecmds.cpp
index 8d511b6..46e533a 100644
--- a/code/debugconsole/consolecmds.cpp
+++ b/code/debugconsole/consolecmds.cpp
@@ -26,8 +26,8 @@
 #include <algorithm>
 
 // ========================= GLOBALS =========================
-SCP_vector<debug_command*> dc_commands;
-typedef SCP_vector<debug_command*>::iterator dc_commands_it;
+debug_command *dc_commands[DC_MAX_COMMANDS];
+int dc_commands_size = 0;
 
 // ========================= LOCALS ==========================
 // dcf_shell commands
@@ -36,23 +36,53 @@ void dc_shell_resize( void );
 void dc_shell_resize_buf( void );
 
 // =================== class debug_command ===================
-debug_command::debug_command(const char *_name, const char *_help, void (*_func)())
-	: name(_name), help(_help), func(_func)
-{
-	dc_commands_it it = std::find_if(dc_commands.begin(), dc_commands.end(), is_dcmd(_name));
-	
-	if (it != dc_commands.end()) {
-		Int3();		// Command already exists! Somebody didn't use the DCF macro as they should've...
+debug_command::debug_command()
+: name(""), help(""), func(NULL) {
+};
+
+debug_command::debug_command(const char *_name, const char *_help, void(*_func)())
+	: name(_name), help(_help), func(_func) {
+	int i = 0;
+	int ret = 0;
+
+	if (dc_commands_size > DC_MAX_COMMANDS) {
+		Error(LOCATION, "Too many debug console commands! Please inform a coder to increase DC_MAX_COMMANDS.");
+		return;
 	}
 
-	dc_commands.push_back(this);
+	// Start the insertion sort by finding where to stick the debug command
+	for (; i < dc_commands_size; ++i) {
+		ret = stricmp(dc_commands[i]->name, _name);
+
+		if (ret == 0) {
+			Error(LOCATION, "Debug Command %s already exists! Please inform a coder immediately.", _name);
+			return;
+		} else if (ret > 0) {
+			// Insert the command here
+			break;
+		} // Else, do nothing
+	}
+
+	// Then, do the insertion
+	if (i < dc_commands_size) {
+		for (int j = dc_commands_size; j > i; --j) {
+			dc_commands[j] = dc_commands[j - 1];
+		}
+		dc_commands[i] = this;
+		dc_commands_size++;
+	} else {
+		dc_commands[dc_commands_size] = this;
+		dc_commands_size++;
+	}
 }
 
 // ============================== IMPLEMENTATIONS =============================
 
 DCF(debug, "Runs a command in debug mode.")
 {
+	int i;
 	SCP_string command = "";
+	
 	Dc_debug_on = true;
 
 	dc_stuff_string_white(command);
@@ -62,16 +92,20 @@ DCF(debug, "Runs a command in debug mode.")
 		return;
 	} // Else, command is present.
 
-	dc_commands_it it = std::find_if(dc_commands.begin(), dc_commands.end(), is_dcmd(command.c_str()));
+	for (i = 0; i < dc_commands_size; ++i) {
+		if (stricmp(dc_commands[i]->name, command.c_str()) == 0) {
+			break;
+		} // Else, continue
+	}
 
-	if (it == dc_commands.end()) {
+	if (i == dc_commands_size) {
 		dc_printf("<debug> Command not found: '%s'\n", command.c_str());
 		return;
-	} // Else, command exists. Run it.
+	} // Else, we found our command
 
 	dc_printf("<debug> Executing command: '%s'\n", command.c_str());
 	// try {
-	(*it)->func();
+	dc_commands[i]->func();
 	// } catch {
 	// }
 
@@ -82,6 +116,7 @@ DCF(help, "Displays the help list." )
 {
 	extern uint DROWS;
 
+	int i;
 	SCP_string command = "";
 
 	dc_maybe_stuff_string_white(command);
@@ -92,14 +127,18 @@ DCF(help, "Displays the help list." )
 		return;
 
 	} else if (command != "") {
-		dc_commands_it it = std::find_if(dc_commands.begin(), dc_commands.end(), is_dcmd(command.c_str()));
+		for (i = 0; i < dc_commands_size; ++i) {
+			if (stricmp(dc_commands[i]->name, command.c_str()) == 0) {
+				break;
+			} // Else, continue
+		}
 
-		if (it == dc_commands.end()) {
+		if (i == dc_commands_size) {
 			dc_printf("Command not found: '%s'\n", command.c_str());
 			return;
-		}
+		} // Else, we found our command
 
-		dc_printf("%s\n", (*it)->help);
+		dc_printf("%s\n", dc_commands[i]->help);
 		return;
 	} // Else, command line is empty, print out the help list
 
@@ -111,12 +150,12 @@ DCF(help, "Displays the help list." )
 	dc_printf("\n");
 
 	dc_printf(" Available commands:\n");
-	for (dc_commands_it it = dc_commands.begin(); it != dc_commands.end(); ++it) {
+	for (i = 0; i < dc_commands_size; ++i) {
 		if (((lastline % DROWS) == 0) && (lastline != 0)) {
 			dc_pause_output();
 		}
 
-		dc_printf(" %s - %s\n", (*it)->name, (*it)->help);
+		dc_printf(" %s - %s\n", dc_commands[i]->name, dc_commands[i]->help);
 	}
 }
 
-- 
1.8.3.msysgit.0

