void _debug( code_part part, const char *function, const char *str, ... ) { va_list ap; static char outputBuffer[MAX_LEN_LOG_LINE]; static unsigned int repeated = 0; /* times current message repeated */ static unsigned int next = 2; /* next total to print update */ static unsigned int prev = 0; /* total on last update */ va_start(ap, str); vssprintf(outputBuffer, str, ap); va_end(ap); ssprintf(inputBuffer[useInputBuffer1 ? 1 : 0], "[%s] %s", function, outputBuffer); if (sstrcmp(inputBuffer[0], inputBuffer[1]) == 0) { // Received again the same line repeated++; if (repeated == next) { if (repeated > 2) { ssprintf(outputBuffer, "last message repeated %u times (total %u repeats)", repeated - prev, repeated); } else { ssprintf(outputBuffer, "last message repeated %u times", repeated - prev); } printToDebugCallbacks(outputBuffer); prev = repeated; next *= 2; } } else { // Received another line, cleanup the old if (repeated > 0 && repeated != prev && repeated != 1) { /* just repeat the previous message when only one repeat occurred */ if (repeated > 2) { ssprintf(outputBuffer, "last message repeated %u times (total %u repeats)", repeated - prev, repeated); } else { ssprintf(outputBuffer, "last message repeated %u times", repeated - prev); } printToDebugCallbacks(outputBuffer); } repeated = 0; next = 2; prev = 0; } if (!repeated) { time_t rawtime; struct tm * timeinfo; char ourtime[15]; //HH:MM:SS time ( &rawtime ); timeinfo = localtime ( &rawtime ); strftime (ourtime,15,"%I:%M:%S",timeinfo); // Assemble the outputBuffer: ssprintf(outputBuffer, "%-8s|%s: %s", code_part_names[part], ourtime, useInputBuffer1 ? inputBuffer[1] : inputBuffer[0]); printToDebugCallbacks(outputBuffer); if (part == LOG_ERROR) { // used to signal user that there was a error condition, and to check the logs. NotifyUserOfError(useInputBuffer1 ? inputBuffer[1] : inputBuffer[0]); } // Throw up a dialog box for users since most don't have a clue to check the dump file for information. Use for (duh) Fatal errors, that force us to terminate the game. if (part == LOG_FATAL) { #if defined(WZ_OS_WIN) char wbuf[512]; ssprintf(wbuf, "%s\n\nPlease check your stderr.txt file in the same directory as the program file for more details. \ \nDo not forget to upload both the stderr.txt file and the warzone2100.rpt file in your bug reports!", useInputBuffer1 ? inputBuffer[1] : inputBuffer[0]); MessageBoxA( NULL, wbuf, "Warzone has terminated unexpectedly", MB_OK|MB_ICONERROR); #elif defined(WZ_OS_MAC) cocoaShowAlert("Warzone has terminated unexpectedly.", "Please check your logs for more details." "\n\nRun Console.app, search for \"wz2100\", and copy that to a file." "\n\nIf you are on 10.4 (Tiger) or 10.5 (Leopard) the crash report" " is in ~/Library/Logs/CrashReporter." " If you are on 10.6 (Snow Leopard), it is in" "\n~/Library/Logs/DiagnosticReports." "\n\nDo not forget to upload and attach those to a bug report at http://developer.wz2100.net/newticket" "\nThanks!", 2); #else const char* popupBuf = useInputBuffer1 ? inputBuffer[1] : inputBuffer[0]; wzFatalDialog(popupBuf); #endif }
void _debug(int line, code_part part, const char *function, const char *str, ...) { va_list ap; static char outputBuffer[MAX_LEN_LOG_LINE]; static unsigned int repeated = 0; /* times current message repeated */ static unsigned int next = 2; /* next total to print update */ static unsigned int prev = 0; /* total on last update */ va_start(ap, str); vssprintf(outputBuffer, str, ap); va_end(ap); if (part == LOG_WARNING) { std::pair<std::map<std::string, int>::iterator, bool> ret; ret = warning_list.insert(std::pair<std::string, int>(std::string(function) + "-" + std::string(outputBuffer), line)); if (ret.second) { ssprintf(inputBuffer[useInputBuffer1 ? 1 : 0], "[%s:%d] %s (**Further warnings of this type are suppressed.)", function, line, outputBuffer); } else { return; // don't bother adding any more } } else { ssprintf(inputBuffer[useInputBuffer1 ? 1 : 0], "[%s:%d] %s", function, line, outputBuffer); } if (sstrcmp(inputBuffer[0], inputBuffer[1]) == 0) { // Received again the same line repeated++; if (repeated == next) { if (repeated > 2) { ssprintf(outputBuffer, "last message repeated %u times (total %u repeats)", repeated - prev, repeated); } else { ssprintf(outputBuffer, "last message repeated %u times", repeated - prev); } printToDebugCallbacks(outputBuffer); prev = repeated; next *= 2; } } else { // Received another line, cleanup the old if (repeated > 0 && repeated != prev && repeated != 1) { /* just repeat the previous message when only one repeat occurred */ if (repeated > 2) { ssprintf(outputBuffer, "last message repeated %u times (total %u repeats)", repeated - prev, repeated); } else { ssprintf(outputBuffer, "last message repeated %u times", repeated - prev); } printToDebugCallbacks(outputBuffer); } repeated = 0; next = 2; prev = 0; } if (!repeated) { time_t rawtime; struct tm *timeinfo; char ourtime[15]; //HH:MM:SS time(&rawtime); timeinfo = localtime(&rawtime); strftime(ourtime, 15, "%I:%M:%S", timeinfo); // Assemble the outputBuffer: ssprintf(outputBuffer, "%-8s|%s: %s", code_part_names[part], ourtime, useInputBuffer1 ? inputBuffer[1] : inputBuffer[0]); printToDebugCallbacks(outputBuffer); if (part == LOG_ERROR) { // used to signal user that there was a error condition, and to check the logs. sstrcpy(errorStore, useInputBuffer1 ? inputBuffer[1] : inputBuffer[0]); errorWaiting = true; } // Throw up a dialog box for users since most don't have a clue to check the dump file for information. Use for (duh) Fatal errors, that force us to terminate the game. if (part == LOG_FATAL) { if (wzIsFullscreen()) { wzToggleFullscreen(); } #if defined(WZ_OS_WIN) char wbuf[512]; ssprintf(wbuf, "%s\n\nPlease check the file (%s) in your configuration directory for more details. \ \nDo not forget to upload the %s file, WZdebuginfo.txt and the warzone2100.rpt files in your bug reports at http://developer.wz2100.net/newticket!", useInputBuffer1 ? inputBuffer[1] : inputBuffer[0], WZ_DBGFile, WZ_DBGFile); MessageBoxA(NULL, wbuf, "Warzone has terminated unexpectedly", MB_OK | MB_ICONERROR); #elif defined(WZ_OS_MAC) int clickedIndex = \ cocoaShowAlert("Warzone has quit unexpectedly.", "Please check your logs and attach them along with a bug report. Thanks!", 2, "Show Log Files & Open Bug Reporter", "Ignore", NULL); if (clickedIndex == 0) { cocoaOpenURL("http://developer.wz2100.net/newticket"); if (WZDebugfilename == NULL) { cocoaShowAlert("Unable to open debug log.", "The debug log subsystem has not yet been initialised.", 2, "Continue", NULL); } else { cocoaSelectFileInFinder(WZDebugfilename); } cocoaOpenUserCrashReportFolder(); } #else const char *popupBuf = useInputBuffer1 ? inputBuffer[1] : inputBuffer[0]; wzFatalDialog(popupBuf); #endif } // Throw up a dialog box for windows users since most don't have a clue to check the stderr.txt file for information // This is a popup dialog used for times when the error isn't fatal, but we still need to notify user what is going on. if (part == LOG_POPUP) { #if defined(WZ_OS_WIN) char wbuf[512]; ssprintf(wbuf, "A non fatal error has occurred.\n\n%s\n\n", useInputBuffer1 ? inputBuffer[1] : inputBuffer[0]); MessageBoxA(NULL, wbuf, "Warzone has detected a problem.", MB_OK | MB_ICONINFORMATION); #elif defined(WZ_OS_MAC) cocoaShowAlert("Warzone has detected a problem.", inputBuffer[useInputBuffer1 ? 1 : 0], 0, "OK", NULL); #endif } }