SCP_string os_get_config_path(const SCP_string& subpath)
{
	// Make path platform compatible
	SCP_string compatiblePath(subpath);
	std::replace(compatiblePath.begin(), compatiblePath.end(), '/', DIR_SEPARATOR_CHAR);

	SCP_stringstream ss;

	if (Cmdline_portable_mode) {
		// Use the current directory
		ss << "." << DIR_SEPARATOR_CHAR << compatiblePath;
		return ss.str();
	}

	// Avoid infinite recursion when checking legacy mode
	if (os_is_legacy_mode()) {
#ifdef WIN32
		// Use the current directory
		ss << ".";
#else
		extern const char* Osreg_user_dir_legacy;
		// Use the home directory
		ss << getenv("HOME") << DIR_SEPARATOR_CHAR << Osreg_user_dir_legacy;
#endif

		ss << DIR_SEPARATOR_CHAR << compatiblePath;
		return ss.str();
	}

	ss << getPreferencesPath() << compatiblePath;

	return ss.str();
}
static SCP_string opengl_shader_get_header(shader_type type_id, int flags, bool has_geo_shader) {
	SCP_stringstream sflags;

	sflags << "#version " << GLSL_version << " core\n";

	if (Detail.lighting < 3) {
		sflags << "#define FLAG_LIGHT_MODEL_BLINN_PHONG\n";
	}

	if (has_geo_shader) {
		// If there is a geometry shader then we define a special preprocessor symbol to make writing shaders easier
		sflags << "#define HAS_GEOMETRY_SHADER\n";
	}

	if (type_id == SDR_TYPE_POST_PROCESS_MAIN || type_id == SDR_TYPE_POST_PROCESS_LIGHTSHAFTS || type_id == SDR_TYPE_POST_PROCESS_FXAA) {
		// ignore looking for variants. main post process, lightshafts, and FXAA shaders need special headers to be hacked in
		opengl_post_shader_header(sflags, type_id, flags);
	}
	else {
		for (int i = 0; i < GL_num_shader_variants; ++i) {
			opengl_shader_variant_t &variant = GL_shader_variants[i];

			if (type_id == variant.type_id && flags & variant.flag) {
				sflags << "#define " << variant.flag_text << "\n";
			}
		}
	}

	return sflags.str();
}
static SCP_string opengl_shader_get_header(shader_type type_id, int flags, shader_stage stage) {
	SCP_stringstream sflags;

	sflags << "#version " << GLSL_version << " core\n";

	if (GL_workaround_clipping_planes) {
		sflags << "#define WORKAROUND_CLIPPING_PLANES\n";
	}

	if (type_id == SDR_TYPE_POST_PROCESS_MAIN || type_id == SDR_TYPE_POST_PROCESS_LIGHTSHAFTS || type_id == SDR_TYPE_POST_PROCESS_FXAA) {
		// ignore looking for variants. main post process, lightshafts, and FXAA shaders need special headers to be hacked in
		opengl_post_shader_header(sflags, type_id, flags);
	}
	else {
		for (int i = 0; i < GL_num_shader_variants; ++i) {
			opengl_shader_variant_t &variant = GL_shader_variants[i];

			if (type_id == variant.type_id && flags & variant.flag) {
				sflags << "#define " << variant.flag_text << "\n";
			}
		}
	}

	return sflags.str();
}
static SCP_string handle_includes(const char* filename, const SCP_string& original) {
	SCP_stringstream output;
	SCP_vector<SCP_string> include_stack;
	auto include_counter = 0;

	handle_includes_impl(include_stack, output, include_counter, filename, original);

	return output.str();
}
Exemple #5
0
		void AssertMessage(const char * text, const char * filename, int linenum, const char * format, ...)
		{
			// We only want to display the file name
			filename = clean_filename(filename);

			SCP_stringstream msgStream;
			msgStream << "Assert: \"" << text << "\"\n";
			msgStream << "File: " << filename << "\n";
			msgStream << "Line: " << linenum << "\n";
			
			if (format != nullptr)
			{
				SCP_string buffer;
				va_list args;

				va_start(args, format);
				vsprintf(buffer, format, args);
				va_end(args);

				msgStream << buffer << "\n";
				mprintf(("ASSERTION: \"%s\" at %s:%d\n %s\n", text, filename, linenum, buffer.c_str()));
			}
			else
			{
				// No additional message
				mprintf(("ASSERTION: \"%s\" at %s:%d\n", text, filename, linenum));
			}

			if (running_unittests) {
				throw AssertException(msgStream.str());
			}

			msgStream << "\n";
			msgStream << dump_stacktrace();

			SCP_string messageText = msgStream.str();
			set_clipboard_text(messageText.c_str());

			messageText = truncateLines(msgStream, Messagebox_lines);
			messageText += "\n[ This info is in the clipboard so you can paste it somewhere now ]\n";
			messageText += "\n\nUse Debug to break into Debugger, Exit will close the application.\n";

			Error(messageText.c_str());
		}
	SCP_string format_version(int major, int minor, int build, int revision)
	{
		SCP_stringstream ss;
		
		ss << major << "." << minor << "." << build;
		
		if (revision != 0)
		{
			ss << "." << revision;
		}
		
		return ss.str();
	}
Exemple #7
0
		void Error(const char * filename, int line, const char * format, ...)
		{
			SCP_string formatText;
			filename = clean_filename(filename);

			va_list args;
			va_start(args, format);
			vsprintf(formatText, format, args);
			va_end(args);

			SCP_stringstream messageStream;
			messageStream << "Error: " << formatText << "\n";
			messageStream << "File: " << filename << "\n";
			messageStream << "Line: " << line << "\n";

			Error(messageStream.str().c_str());
		}
SCP_string dump_stacktrace()
{

#if defined( SHOW_CALL_STACK ) && defined( PDB_DEBUGGING )
    /* Dump the callstack */
    SCP_DebugCallStack callStack;
    SCP_DumpStack(dynamic_cast< SCP_IDumpHandler* >(&callStack));

    return callStack.DumpToString();
#elif defined( SHOW_CALL_STACK )
    SCP_stringstream stream;

    DumpCallsStack(stream);

    return stream.str();
#else
    return "No stacktrace available!";
#endif
}
void FrameProfiler::processFrame() {

	std::lock_guard<std::mutex> vectorGuard(_eventsMutex);

	std::sort(_bufferedEvents.begin(), _bufferedEvents.end(), event_sorter);

	SCP_stringstream stream;

	SCP_vector<profile_sample> samples;

	bool start_found = false;
	bool end_found = false;
	uint64_t start_profile_time = 0;
	uint64_t end_profile_time = 0;

	for (auto& event : _bufferedEvents) {
		if (!start_found) {
			start_profile_time = event.timestamp;
			start_found = true;
		}
		if (!end_found) {
			end_profile_time = event.timestamp;
			end_found = true;
		}

		switch (event.type) {
			case EventType::Begin:
				process_begin(samples, event);
				break;
			case EventType::End:
				process_end(samples, event);
				break;
			default:
				break;
		}
	}
	_bufferedEvents.clear();

	dump_output(stream, start_profile_time, end_profile_time, samples);

	content = stream.str();
}
void HudGaugeThrottle::initMatchSpeedOffsets(int x, int y, bool custom)
{
	Match_speed_offsets[0] = x;
	Match_speed_offsets[1] = y;
	Use_custom_match_speed = custom;

	font::FSFont* fsFont = font::get_font(font_num);

	if (fsFont->getType() == font::VFNT_FONT)
	{
		ubyte sc = lcl_get_font_index(font_num);
		// NOTE: default to normal m because either
		// a) the german font has no special m (its an a)
		// b) the font has no special characters
		if (sc == 0 || Lcl_gr) {
			Match_speed_icon = 'm';
		}
		else {
			Match_speed_icon = sc + 3;
		}
		Match_speed_draw_background = false;
	}
	else
	{
		// Default version for other fonts, draw a black character on a rectangle
		Match_speed_icon = 'm';
		Match_speed_draw_background = true;
	}
	SCP_stringstream stream;

	stream << static_cast<char>(Match_speed_icon);
	
	const SCP_string& iconStr = stream.str();

	gr_get_string_size(&Match_speed_icon_width, nullptr, iconStr.c_str());
}
static SCP_string get_shader_header(shader_type type_id, int flags) {
	SCP_stringstream sflags;

#ifdef __APPLE__
	sflags << "#version 120\n";
	sflags << "#define APPLE\n";
#endif

	if (type_id == SDR_TYPE_POST_PROCESS_MAIN || type_id == SDR_TYPE_POST_PROCESS_LIGHTSHAFTS || type_id == SDR_TYPE_POST_PROCESS_FXAA) {
		// ignore looking for variants. main post process, lightshafts, and FXAA shaders need special headers to be hacked in
		opengl_post_shader_header(sflags, type_id, flags);
	}
	else {
		for (int i = 0; i < GL_num_shader_variants; ++i) {
			opengl_shader_variant_t &variant = GL_shader_variants[i];

			if (type_id == variant.type_id && flags & variant.flag) {
				sflags << "#define " << variant.flag_text << "\n";
			}
		}
	}

	return sflags.str();
}
Exemple #12
0
SCP_string dump_stacktrace()
{
#ifdef HAVE_EXECINFO_H
	// The following is adapted from here: https://panthema.net/2008/0901-stacktrace-demangled/
	const int ADDR_SIZE = 64;
	void *addresses[ADDR_SIZE];
	
	auto numstrings = backtrace(addresses, ADDR_SIZE);
	
	if (numstrings == 0)
	{
		return "No stacktrace available (possibly corrupt)";
	}
	
	auto symbollist = backtrace_symbols(addresses, numstrings);
	
	if (symbollist == nullptr)
	{
		return "No stacktrace available (possibly corrupt)";
	}
	
	// Demangle c++ function names to a more readable format using the ABI functions
	// TODO: Maybe add configure time checks to check if the required features are available
	SCP_stringstream stackstream;
#ifdef HAVE_CXXAPI_H
	size_t funcnamesize = 256;
	char* funcname = reinterpret_cast<char*>(malloc(funcnamesize));
	
	// iterate over the returned symbol lines. skip the first, it is the
	// address of this function.
	for (int i = 1; i < numstrings; i++)
	{
		char *begin_name = 0, *begin_offset = 0, *end_offset = 0;

		// find parentheses and +address offset surrounding the mangled name:
		// ./module(function+0x15c) [0x8048a6d]
		for (char *p = symbollist[i]; *p; ++p)
		{
			if (*p == '(')
				begin_name = p;
			else if (*p == '+')
				begin_offset = p;
			else if (*p == ')' && begin_offset) {
				end_offset = p;
				break;
			}
		}

		if (begin_name && begin_offset && end_offset && begin_name < begin_offset)
		{
			*begin_name++ = '\0';
			*begin_offset++ = '\0';
			*end_offset = '\0';

			// mangled name is now in [begin_name, begin_offset) and caller
			// offset in [begin_offset, end_offset). now apply
			// __cxa_demangle():

			int status;
			char* ret = abi::__cxa_demangle(begin_name, funcname, &funcnamesize, &status);
			
			if (status == 0) {
				funcname = ret; // use possibly realloc()-ed string
				stackstream << "  " << symbollist[i] << " : " << funcname << "+" << begin_offset << "\n";
			}
			else {
				// demangling failed. Output function name as a C function with
				// no arguments.
				stackstream << "  " << symbollist[i] << " : " << begin_name << "()+" << begin_offset << "\n";
			}
		}
		else
		{
			// couldn't parse the line? print the whole line.
			stackstream << "  " << symbollist[i] << "\n";
		}
	}
	free(funcname);
#else
	for (auto i = 0; i < numstrings; ++i) {
		stackstream << symbollist[i] << "\n";
	}
#endif

	free(symbollist);

	return stackstream.str();
#else
	return "No stacktrace available";
#endif
}
Exemple #13
0
		void ReleaseWarning(const char* filename, int line, const char* format, ...)
		{
			Global_warning_count++;

			filename = clean_filename(filename);

			// output to the debug log before anything else (so that we have a complete record)

			SCP_string formatMessage;
			va_list args;
			va_start(args, format);
			vsprintf(formatMessage, format, args);
			va_end(args);


			SCP_string printfString = formatMessage;
			std::transform(printfString.begin(), printfString.end(), printfString.begin(), replaceNewline);

			mprintf(("WARNING: \"%s\" at %s:%d\n", printfString.c_str(), filename, line));

			// now go for the additional popup window, if we want it ...
			if (Cmdline_noninteractive) {
				return;
			}

			if (running_unittests) {
				throw AssertException(printfString);
			}

			SCP_stringstream boxMsgStream;
			boxMsgStream << "Warning: " << formatMessage << "\n";
			boxMsgStream << "File: " << filename << "\n";
			boxMsgStream << "Line: " << line << "\n";

			boxMsgStream << "\n";
			boxMsgStream << dump_stacktrace();

			set_clipboard_text(boxMsgStream.str().c_str());

			SCP_string boxMessage = truncateLines(boxMsgStream, Messagebox_lines);
			boxMessage += "\n[ This info is in the clipboard so you can paste it somewhere now ]\n";
			boxMessage += "\n\nUse Debug to break into Debugger\n";

			const SDL_MessageBoxButtonData buttons[] = {
				{ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 2, "Exit" },
				{ SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 1, "Continue" },
				{ /* .flags, .buttonid, .text */        0, 0, "Debug" },
			};

			SDL_MessageBoxData boxData;
			memset(&boxData, 0, sizeof(boxData));

			boxData.buttons = buttons;
			boxData.numbuttons = 3;
			boxData.colorScheme = nullptr;
			boxData.flags = SDL_MESSAGEBOX_WARNING;
			boxData.message = boxMessage.c_str();
			boxData.title = "Warning!";
			boxData.window = os::getSDLMainWindow();

			gr_activate(0);

			int buttonId;
			if (SDL_ShowMessageBox(&boxData, &buttonId) < 0)
			{
				// Call failed
				exit(1);
			}

			switch (buttonId)
			{
			case 2:
				exit(1);

			case 0:
				Int3();
				break;

			default:
				break;
			}

			gr_activate(1);
		}
Exemple #14
0
		void Error(const char* text)
		{
			mprintf(("\n%s\n", text));

			if (Cmdline_noninteractive) {
				abort();
				return;
			}

			if (running_unittests) {
				throw ErrorException(text);
			}

			SCP_stringstream messageStream;
			messageStream << text << "\n";
			messageStream << dump_stacktrace();

			SCP_string fullText = messageStream.str();
			set_clipboard_text(fullText.c_str());

			fullText = truncateLines(messageStream, Messagebox_lines);

			fullText += "\n[ This info is in the clipboard so you can paste it somewhere now ]\n";
			fullText += "\n\nUse Debug to break into Debugger, Exit will close the application.\n";

			const SDL_MessageBoxButtonData buttons[] = {
				{ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 1, "Exit" },
				{ /* .flags, .buttonid, .text */        0, 0, "Debug" },
			};

			SDL_MessageBoxData boxData;
			memset(&boxData, 0, sizeof(boxData));

			boxData.buttons = buttons;
			boxData.numbuttons = 2;
			boxData.colorScheme = nullptr;
			boxData.flags = SDL_MESSAGEBOX_ERROR;
			boxData.message = text;
			boxData.title = "Error!";
			boxData.window = os::getSDLMainWindow();

			gr_activate(0);

			int buttonId;
			if (SDL_ShowMessageBox(&boxData, &buttonId) < 0)
			{
				// Call failed
				exit(1);
			}

			switch (buttonId)
			{
			case 1:
				exit(1);

			default:
				Int3();
				break;
			}
			gr_activate(1);
		}
Exemple #15
0
		void LuaError(lua_State * L, const char * format, ...)
		{
			SCP_stringstream msgStream;
			
			//WMC - if format is set to NULL, assume this is acting as an
			//error handler for Lua.
			if (format == NULL)
			{
				msgStream << "LUA ERROR: " << lua_tostring(L, -1);
				lua_pop(L, -1);
			}
			else
			{
				SCP_string formatText;

				va_list args;
				va_start(args, format);
				vsprintf(formatText, format, args);
				va_end(args);

				msgStream << formatText;
			}

			msgStream << "\n";
			msgStream << "\n";

			msgStream << Separator;
			msgStream << "ADE Debug:";
			msgStream << "\n";

			msgStream << Separator;
			LuaDebugPrint(msgStream, Ade_debug_info);
			msgStream << Separator;

			msgStream << "\n";
			msgStream << "\n";

			msgStream << Separator;

			// Get the stack via the debug.traceback() function
			lua_getglobal(L, LUA_DBLIBNAME);

			if (!lua_isnil(L, -1))
			{
				msgStream << "\n";
				lua_getfield(L, -1, "traceback");
				lua_remove(L, -2);

				if (lua_pcall(L, 0, 1, 0) != 0)
					msgStream << "Error while retrieving stack: " << lua_tostring(L, -1);
				else
					msgStream << lua_tostring(L, -1);

				lua_pop(L, 1);
			}
			msgStream << "\n";

			msgStream << Separator;

			char stackText[1024];
			stackText[0] = '\0';
			scripting::ade_stackdump(L, stackText);
			msgStream << stackText;
			msgStream << "\n";
			msgStream << Separator;

			mprintf(("Lua Error: %s\n", msgStream.str().c_str()));

			if (Cmdline_noninteractive) {
				exit(1);
				return;
			}

			if (running_unittests) {
				throw LuaErrorException(msgStream.str());
			}

			set_clipboard_text(msgStream.str().c_str());

			// truncate text
			auto truncatedText = truncateLines(msgStream, Messagebox_lines);

			SCP_stringstream boxTextStream;
			boxTextStream << truncatedText << "\n";

			boxTextStream << "\n[ This info is in the clipboard so you can paste it somewhere now ]\n";

			auto boxText = boxTextStream.str();
			const SDL_MessageBoxButtonData buttons[] = {
				{ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 2, "Exit" },
				{ SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 1, "Continue" },
				{ /* .flags, .buttonid, .text */        0, 0, "Debug" },
			};

			SDL_MessageBoxData boxData;
			memset(&boxData, 0, sizeof(boxData));

			boxData.buttons = buttons;
			boxData.numbuttons = 3;
			boxData.colorScheme = nullptr;
			boxData.flags = SDL_MESSAGEBOX_ERROR;
			boxData.message = boxText.c_str();
			boxData.title = "Error!";
			boxData.window = os::getSDLMainWindow();

			gr_activate(0);

			int buttonId;
			if (SDL_ShowMessageBox(&boxData, &buttonId) < 0)
			{
				// Call failed
				buttonId = 1; // No action
			}

			switch (buttonId)
			{
			case 2:
				exit(1);

			case 0:
				Int3();
				break;

			default:
				break;
			}

			gr_activate(1);
		}