#include #include #include #include "global.hpp" #include "error.hpp" #include "stream.hpp" // Disable annoying warning 4996: "'function' was declared deprecated" #if CHECK_MSC_VERSION(14, 0) # pragma warning(push) # pragma warning(disable: 4996) #endif namespace Check { Stream input; Stream output; Stream answer; namespace Auxiliary { static std::string logName; static bool isMessageEmpty(const char *format, const va_list argList) { char buffer[4] = ""; vsnprintf(buffer, sizeof buffer - 1, format, argList); return buffer[0] == '\0'; } static void exitArgs( const Decision result, const char *format, const va_list argList) { if (result == SolutionAccepted && !output.seekEnd()) incite(PresentationError, "Extra information"); FILE *logFile = stdout; if (!logName.empty()) { logFile = fopen(logName.c_str(), "wt"); if (logFile == NULL) { logName.clear(); raise( UnhandledError, "Log file \'%s\' cannot be opened", logName.c_str()); } } static const char *ExitCodeNames[] = { "OK", "Wrong Answer", "Presentation Error", "Unhandled Error" }; fputs(ExitCodeNames[result], logFile); if (!isMessageEmpty(format, argList)) { fputs(": ", logFile); vfprintf(logFile, format, argList); } fputc('\n', logFile); if (!logName.empty() && fclose(logFile) != 0) { logName.clear(); raise( UnhandledError, "Log file \'%s\' cannot be closed", logName.c_str()); } input.close(); output.close(); answer.close(); std::exit(exitCode(result)); } } void init(int argsCount, char *args[]) { // Substitute terminate function to correct report uncaught exceptions std::set_terminate(terminateLibrary); if (argsCount < 4 || 5 < argsCount) incite(UnhandledError, "Usage: INPUT OUTPUT ANSWER [LOG]"); if (argsCount == 5) Auxiliary::logName = args[4]; input.open(args[1], InputStream); output.open(args[2], OutputStream); answer.open(args[3], AnswerStream); } int exitCode(const Decision result) { #if defined(CHECK_EJUDGE) static const int ExitCodes[] = { 0, 5, 4, 6 }; #else static const int ExitCodes[] = { 0, 1, 2, 3 }; #endif return ExitCodes[result]; } void exit(const Decision result, const char *format, ...) { va_list argList; va_start(argList, format); Auxiliary::exitArgs(result, format, argList); va_end(argList); } void exitUnless(const bool cond, const Decision result, const char *format, ...) { if (!cond) { va_list argList; va_start(argList, format); Auxiliary::exitArgs(result, format, argList); va_end(argList); } } } #if CHECK_MSC_VERSION(14, 0) # pragma warning(pop) #endif