#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "uoj_env.h" using namespace std; /*====================== parameter ==================== */ struct RunLimit { int time; int memory; int output; RunLimit() { } RunLimit(const int &_time, const int &_memory, const int &_output) : time(_time), memory(_memory), output(_output) { } }; const RunLimit RL_DEFAULT = RunLimit(1, 256, 64); const RunLimit RL_JUDGER_DEFAULT = RunLimit(600, 1024, 128); const RunLimit RL_CHECKER_DEFAULT = RunLimit(5, 256, 64); const RunLimit RL_VALIDATOR_DEFAULT = RunLimit(5, 256, 64); const RunLimit RL_MARKER_DEFAULT = RunLimit(5, 256, 64); const RunLimit RL_COMPILER_DEFAULT = RunLimit(15, 512, 64); struct PointInfo { int num; int scr; int ust, usm; string info, in, out, res; PointInfo(const int &_num, const int &_scr, const int &_ust, const int &_usm, const string &_info, const string &_in, const string &_out, const string &_res) : num(_num), scr(_scr), ust(_ust), usm(_usm), info(_info), in(_in), out(_out), res(_res) { } }; struct CustomTestInfo { int ust, usm; string info, exp, out; CustomTestInfo(const int &_ust, const int &_usm, const string &_info, const string &_exp, const string &_out) : ust(_ust), usm(_usm), info(_info), exp(_exp), out(_out) { } }; struct RunResult { int type; int ust, usm; int exit_code; static RunResult failed_result() { RunResult res; res.type = RS_JGF; res.ust = -1; res.usm = -1; return res; } }; struct RunCheckerResult { int type; int ust, usm; int scr; string info; static RunCheckerResult failed_result() { RunCheckerResult res; res.type = RS_JGF; res.ust = -1; res.usm = -1; res.scr = 0; res.info = "Checker Judgment Failed"; return res; } }; struct RunValidatorResult { int type; int ust, usm; bool succeeded; string info; static RunValidatorResult failed_result() { RunValidatorResult res; res.type = RS_JGF; res.ust = -1; res.usm = -1; res.succeeded = 0; res.info = "Validator Judgment Failed"; return res; } }; struct RunCompilerResult { int type; int ust, usm; bool succeeded; string info; static RunCompilerResult failed_result() { RunCompilerResult res; res.type = RS_JGF; res.ust = -1; res.usm = -1; res.succeeded = false; res.info = "Compile Failed"; return res; } }; int problem_id; string main_path; string work_path; string data_path; string result_path; int tot_time = 0; int max_memory = 0; int tot_score = 0; ostringstream details_out; //vector points_info; map config; /*==================== parameter End ================== */ /*========================== execute ====================== */ string escapeshellarg(const string &arg) { string res = "'"; for (size_t i = 0; i < arg.size(); i++) { if (arg[i] == '\'') { res += "'\\''"; } else { res += arg[i]; } } res += "'"; return res; } string realpath(const string &path) { char real[PATH_MAX + 1]; if (realpath(path.c_str(), real) == NULL) { return ""; } return real; } int execute(const char *cmd) { return system(cmd); } int executef(const char *fmt, ...) { const int MaxL = 512; char cmd[MaxL]; va_list ap; va_start(ap, fmt); int res = vsnprintf(cmd, MaxL, fmt, ap); if (res < 0 || res >= MaxL) { return -1; } res = execute(cmd); va_end(ap); return res; } /*======================== execute End ==================== */ /*========================= file ====================== */ /* bool file_exist(const string &name) { return access(name.c_str(), F_OK); } */ string file_preview(const string &name, const size_t &len = 100) { FILE *f = fopen(name.c_str(), "r"); if (f == NULL) { return ""; } string res = ""; int c; while (c = fgetc(f), c != EOF && res.size() < len + 4) { res += c; } if (res.size() > len + 3) { res.resize(len); res += "..."; } fclose(f); return res; } void file_hide_token(const string &name, const string &token) { executef("cp %s %s.bak", name.c_str(), name.c_str()); FILE *rf = fopen((name + ".bak").c_str(), "r"); FILE *wf = fopen(name.c_str(), "w"); int c; for (int i = 0; i <= (int)token.length(); i++) { c = fgetc(rf); if (c != (i < (int)token.length() ? token[i] : '\n')) { fprintf(wf, "Unauthorized output\n"); fclose(rf); fclose(wf); return; } } while (c = fgetc(rf), c != EOF) { fputc(c, wf); } fclose(rf); fclose(wf); } /* string read_file (FILE *file, const string &s, int t = (int) 1e9) { int ch; string res = ""; int l = t + 4; while (ch = next(file), ch != EOF && l) res += ch, --l; if ((int)res.size() > t + 3) { res.resize(t); res += "..."; } fclose(file); if (res == "") return s; return res; } string read_file (const string &name, const string &s, int t = (int) 1e9) { if (file_exist(name)) return s; return read_file(fopen(name.c_str(), "r"), s, t); } */ /* bool file_compare(const char *fileA, const char *fileB, const int &mark) { FILE *A = fopen(fileA, "r"); FILE *B = fopen(fileB, "r"); int chA = 'a'; int chB = 'a'; bool result = true; if (mark == 0) { do if ((chA = fgetc(A)) != (chB = fgetc(B))) { result = false; break; } while (chA != EOF && chB != EOF); } else { do { chA = fgetc(A); if (chB != EOF) chB = fgetc(B); if (chA == '\r') chA = fgetc(A); if (chB == '\r') chB = fgetc(B); if (chB == chA) continue; if (chA == EOF) swap(chA, chB), swap(A, B); if (chB == EOF) { if (chA != ' ' && chA != '\n') { result = false; break; } else continue; } if (chB == '\n') swap(chA, chB), swap(A, B); if (chA == '\n') { while (chB == ' ') chB = fgetc(B); if (chB == '\r') chB = fgetc(B); if (chB == chA || chB == EOF) continue; } result = false; break; } while (chA != EOF); } fclose(A); fclose(B); return result; } bool file_compare(const string &fileA, const string &fileB, const int &mark) { return file_compare(fileA.c_str(), fileB.c_str(), mark); }*/ /*======================= file End ==================== */ /*====================== info print =================== */ template inline string vtos(const T &v) { ostringstream sout; sout << v; return sout.str(); } inline string htmlspecialchars(const string &s) { string r; for (int i = 0; i < (int)s.length(); i++) { switch (s[i]) { case '&' : r += "&"; break; case '<' : r += "<"; break; case '>' : r += ">"; break; case '"' : r += """; break; case '\0': r += "\\0"; break; default : r += s[i]; break; } } return r; } inline string info_str(int id) { switch (id) { case RS_MLE: return "Memory Limit Exceeded"; case RS_TLE: return "Time Limit Exceeded"; case RS_OLE: return "Output Limit Exceeded"; case RS_RE : return "Runtime Error"; case RS_DGS: return "Dangerous Syscalls"; case RS_JGF: return "Judgment Failed"; /* case RS_SPJ_RE : return "Special Judge Runtime Error"; case RS_SPJ_MLE: return "Special Judge Memory Limit Exceeded"; case RS_SPJ_OLE: return "Special Judge Output Limit Exceeded"; case RS_SPJ_TLE: return "Special Judge Time Limit Exceeded"; case RS_SPJ_DGS: return "Special Judge Dangerous Syscalls"; case RS_SPJ_JGF: return "Special Judge Judgement Failed"; case RS_HK_MLE: return "Hack Successfully : Memory Limit Exceeded"; case RS_HK_TLE: return "Hack Successfully : Time Limit Exceeded"; case RS_HK_OLE: return "Hack Successfully : Output LImit Exceeded"; case RS_HK_RE: return "Hack Successfully : Runtime Error"; case RS_HK_DGS: return "Hack Successfully : Dangerous Syscalls"; case RS_HK_JGF: return "Hack Successfully : Judgement Failed"; case RS_HK_SPJ_RE: return "Hack Successfully : Special Judge Runtime Error"; case RS_HK_SPJ_MLE: return "Hack Successfully : Special Judge Memory Limit Exceeded"; case RS_HK_SPJ_OLE: return "Hack Successfully : Special Judge Output Limit Exceeded"; case RS_HK_SPJ_TLE: return "Hack Successfully : Special Judge Time Limit Exceeded"; case RS_HK_SPJ_DGS: return "Hack Successfully : Special Judge Dangerous Syscalls"; case RS_HK_SPJ_JGF: return "Hack Successfully : Special Judge Judgement Failed"; */ default : return "Unknown Result"; } } inline string info_str(const RunResult &p) { return info_str(p.type); } void add_point_info(const PointInfo &info) { if (info.num >= 0) { if(info.ust >= 0) { tot_time += info.ust; } if(info.usm >= 0) { max_memory = max(max_memory, info.usm); } } tot_score += info.scr; details_out << "" << endl; details_out << "" << htmlspecialchars(info.in) << "" << endl; details_out << "" << htmlspecialchars(info.out) << "" << endl; details_out << "" << htmlspecialchars(info.res) << "" << endl; details_out << "" << endl; } void add_custom_test_info(const CustomTestInfo &info) { if(info.ust >= 0) { tot_time += info.ust; } if(info.usm >= 0) { max_memory = max(max_memory, info.usm); } details_out << "" << endl; if (!info.exp.empty()) { details_out << info.exp << endl; } details_out << "" << htmlspecialchars(info.out) << "" << endl; details_out << "" << endl; } void add_subtask_info(const int &num, const int &scr, const string &info, const vector &points) { details_out << "" << endl; for (vector::const_iterator it = points.begin(); it != points.end(); it++) { add_point_info(*it); } details_out << "" << endl; } void end_judge_ok() { FILE *fres = fopen((result_path + "/result.txt").c_str(), "w"); fprintf(fres, "score %d\n", tot_score); fprintf(fres, "time %d\n", tot_time); fprintf(fres, "memory %d\n", max_memory); fprintf(fres, "details\n"); fprintf(fres, "\n"); fprintf(fres, "%s", details_out.str().c_str()); fprintf(fres, "\n"); fclose(fres); exit(0); } void end_judge_judgement_failed(const string &info) { FILE *fres = fopen((result_path + "/result.txt").c_str(), "w"); fprintf(fres, "error Judgment Failed\n"); fprintf(fres, "details\n"); fprintf(fres, "%s\n", htmlspecialchars(info).c_str()); fclose(fres); exit(1); } void end_judge_compile_error(const RunCompilerResult &res) { FILE *fres = fopen((result_path + "/result.txt").c_str(), "w"); fprintf(fres, "error Compile Error\n"); fprintf(fres, "details\n"); fprintf(fres, "%s\n", htmlspecialchars(res.info).c_str()); fclose(fres); exit(0); } /* void put_info(int num, int scr, int ust, int usm, const char *s, const char *in, const char *out, const char *res) { return put_info(num, scr, ust, usm, string(s), string(in), string(out), string(res)); } void put_info(int num, int scr, const string &s, const string &in, const string &out, const string &res) { return put_info(num, scr, -1, -1, s, in, out, res); } void put_info(int num, int scr, const char *s, const char *in, const char *out, const char *res) { return put_info(num, scr, -1, -1, string(s), string(in), string(out), string(res)); } void end_info(int scr) { return put_info(0, scr, -1, -1, "", "", "", ""); } */ void report_judge_status(const char *status) { FILE *f = fopen((result_path + "/cur_status.txt").c_str(), "a"); if (f == NULL) { return; } if (flock(fileno(f), LOCK_EX) != -1) { if (ftruncate(fileno(f), 0) != -1) { fprintf(f, "%s\n", status); fflush(f); } flock(fileno(f), LOCK_UN); } fclose(f); } bool report_judge_status_f(const char *fmt, ...) { const int MaxL = 512; char status[MaxL]; va_list ap; va_start(ap, fmt); int res = vsnprintf(status, MaxL, fmt, ap); if (res < 0 || res >= MaxL) { return false; } report_judge_status(status); va_end(ap); return true; } /*==================== info print End ================= */ /*====================== config set =================== */ void print_config() { for (map::iterator it = config.begin(); it != config.end(); ++it) { cerr << it->first << " = " << it->second << endl; } } void load_config(const string &filename) { ifstream fin(filename.c_str()); if (!fin) { return; } string key; string val; while (fin >> key >> val) { config[key] = val; } } string conf_str(const string &key, int num, const string &val) { ostringstream sout; sout << key << "_" << num; if (config.count(sout.str()) == 0) { return val; } return config[sout.str()]; } string conf_str(const string &key, const string &val) { if (config.count(key) == 0) { return val; } return config[key]; } string conf_str(const string &key) { return conf_str(key, ""); } int conf_int(const string &key, const int &val) { if (config.count(key) == 0) { return val; } return atoi(config[key].c_str()); } int conf_int(const string &key, int num, const int &val) { ostringstream sout; sout << key << "_" << num; if (config.count(sout.str()) == 0) { return conf_int(key, val); } return atoi(config[sout.str()].c_str()); } int conf_int(const string &key) { return conf_int(key, 0); } string conf_input_file_name(int num) { ostringstream name; if (num < 0) { name << "ex_"; } name << conf_str("input_pre", "input") << abs(num) << "." << conf_str("input_suf", "txt"); return name.str(); } string conf_output_file_name(int num) { ostringstream name; if (num < 0) { name << "ex_"; } name << conf_str("output_pre", "output") << abs(num) << "." << conf_str("output_suf", "txt"); return name.str(); } RunLimit conf_run_limit(string pre, const int &num, const RunLimit &val) { if (!pre.empty()) { pre += "_"; } RunLimit limit; limit.time = conf_int(pre + "time_limit", num, val.time); limit.memory = conf_int(pre + "memory_limit", num, val.memory); limit.output = conf_int(pre + "output_limit", num, val.output); return limit; } RunLimit conf_run_limit(const int &num, const RunLimit &val) { return conf_run_limit("", num, val); } void conf_add(const string &key, const string &val) { if (config.count(key)) return; config[key] = val; } bool conf_has(const string &key) { return config.count(key) != 0; } bool conf_is(const string &key, const string &val) { if (config.count(key) == 0) return false; return config[key] == val; } /*==================== config set End ================= */ /*========================== run ====================== */ struct RunProgramConfig { vector readable_file_names; // other than stdin string result_file_name; string input_file_name; string output_file_name; string error_file_name; string type; string work_path; RunLimit limit; vector argv; RunProgramConfig() { int p = 1; while (conf_str("readable", p, "") != "") { readable_file_names.push_back(conf_str("readable", p, "")); p++; } result_file_name = result_path + "/run_program_result.txt"; type = "default"; work_path = ::work_path; for (vector::iterator it = readable_file_names.begin(); it != readable_file_names.end(); it++) { if (!it->empty() && (*it)[0] != '/') { *it = ::work_path + "/" + *it; } } } void set_argv(const char *program_name, ...) { argv.clear(); argv.push_back(program_name); va_list vl; va_start(vl, program_name); for (const char *arg = va_arg(vl, const char *); arg; arg = va_arg(vl, const char *)) { argv.push_back(arg); } va_end(vl); } }; RunResult vrun_program( const char *run_program_result_file_name, const char *input_file_name, const char *output_file_name, const char *error_file_name, const RunLimit &limit, const vector &rest) { ostringstream sout; sout << main_path << "/run/run_program" << " " << ">" << escapeshellarg(run_program_result_file_name) << " " << "--in=" << escapeshellarg(input_file_name) << " " <<"--out=" << escapeshellarg(output_file_name) << " " << "--err=" << escapeshellarg(error_file_name) << " " << "--tl=" << limit.time << " " << "--ml=" << limit.memory << " " << "--ol=" << limit.output /*<< " " << "--show-trace-details"*/; for (vector::const_iterator it = rest.begin(); it != rest.end(); it++) { sout << " " << escapeshellarg(*it); } RunResult res; if (execute(sout.str().c_str()) != 0) { return RunResult::failed_result(); } FILE *fres = fopen(run_program_result_file_name, "r"); if (fres != NULL && fscanf(fres, "%d %d %d %d", &res.type, &res.ust, &res.usm, &res.exit_code) != 4) { return RunResult::failed_result(); } fclose(fres); return res; } RunResult run_program(const RunProgramConfig &rpc) { ostringstream sout; sout << main_path << "/run/run_program" << " " << ">" << escapeshellarg(rpc.result_file_name) << " " << "--in=" << escapeshellarg(rpc.input_file_name) << " " <<"--out=" << escapeshellarg(rpc.output_file_name) << " " << "--err=" << escapeshellarg(rpc.error_file_name) << " " << "--tl=" << rpc.limit.time << " " << "--ml=" << rpc.limit.memory << " " << "--ol=" << rpc.limit.output << " " << "--type=" << rpc.type << " " << "--work-path=" << rpc.work_path; for (vector::const_iterator it = rpc.readable_file_names.begin(); it != rpc.readable_file_names.end(); it++) { sout << " " << "--add-readable=" << escapeshellarg(*it); } for (vector::const_iterator it = rpc.argv.begin(); it != rpc.argv.end(); it++) { sout << " " << escapeshellarg(*it); } RunResult res; if (execute(sout.str().c_str()) != 0) { return RunResult::failed_result(); } FILE *fres = fopen(rpc.result_file_name.c_str(), "r"); if (fres != NULL && fscanf(fres, "%d %d %d %d", &res.type, &res.ust, &res.usm, &res.exit_code) != 4) { return RunResult::failed_result(); } fclose(fres); return res; } RunResult run_program( const char *run_program_result_file_name, const char *input_file_name, const char *output_file_name, const char *error_file_name, const RunLimit &limit, ...) { vector argv; va_list vl; va_start(vl, limit); for (const char *arg = va_arg(vl, const char *); arg; arg = va_arg(vl, const char *)) { argv.push_back(arg); } va_end(vl); return vrun_program(run_program_result_file_name, input_file_name, output_file_name, error_file_name, limit, argv); } RunValidatorResult run_validator( const string &input_file_name, const RunLimit &limit, const string &program_name) { RunResult ret = run_program( (string(result_path) + "/run_validator_result.txt").c_str(), input_file_name.c_str(), "/dev/null", (string(result_path) + "/validator_error.txt").c_str(), limit, program_name.c_str(), NULL); RunValidatorResult res; res.type = ret.type; res.ust = ret.ust; res.usm = ret.usm; if (ret.type != RS_AC || ret.exit_code != 0) { res.succeeded = false; res.info = file_preview(result_path + "/validator_error.txt"); } else { res.succeeded = true; } return res; } RunCheckerResult run_checker( const RunLimit &limit, const string &program_name, const string &input_file_name, const string &output_file_name, const string &answer_file_name) { RunResult ret = run_program( (string(result_path) + "/run_checker_result.txt").c_str(), "/dev/null", "/dev/null", (string(result_path) + "/checker_error.txt").c_str(), limit, ("--add-readable=" + input_file_name).c_str(), ("--add-readable=" + output_file_name).c_str(), ("--add-readable=" + answer_file_name).c_str(), program_name.c_str(), realpath(input_file_name).c_str(), realpath(output_file_name).c_str(), realpath(answer_file_name).c_str(), NULL); RunCheckerResult res; res.type = ret.type; res.ust = ret.ust; res.usm = ret.usm; if (ret.type != RS_AC) { res.scr = 0; } else { FILE *fres = fopen((result_path + "/checker_error.txt").c_str(), "r"); char type[21]; if (fres == NULL || fscanf(fres, "%20s", type) != 1) { return RunCheckerResult::failed_result(); } if (strcmp(type, "ok") == 0) { res.scr = 100; } else if (strcmp(type, "points") == 0) { double d; if (fscanf(fres, "%lf", &d) != 1) { return RunCheckerResult::failed_result(); } else { res.scr = (int)floor(100 * d + 0.5); } } else { res.scr = 0; } fclose(fres); } res.info = file_preview(result_path + "/checker_error.txt"); return res; } RunCompilerResult run_compiler(const char *path, ...) { vector argv; argv.push_back("--type=compiler"); argv.push_back(string("--work-path=") + path); va_list vl; va_start(vl, path); for (const char *arg = va_arg(vl, const char *); arg; arg = va_arg(vl, const char *)) { argv.push_back(arg); } va_end(vl); RunResult ret = vrun_program( (result_path + "/run_compiler_result.txt").c_str(), "/dev/null", "stderr", (result_path + "/compiler_result.txt").c_str(), RL_COMPILER_DEFAULT, argv); RunCompilerResult res; res.type = ret.type; res.ust = ret.ust; res.usm = ret.usm; res.succeeded = ret.type == RS_AC && ret.exit_code == 0; if (!res.succeeded) { if (ret.type == RS_AC) { res.info = file_preview(result_path + "/compiler_result.txt", 500); } else if (ret.type == RS_JGF) { res.info = "No Comment"; } else { res.info = "Compiler " + info_str(ret.type); } } return res; } RunResult run_submission_program( const string &input_file_name, const string &output_file_name, const RunLimit &limit, const string &name, RunProgramConfig rpc = RunProgramConfig()) { string lang = conf_str(string(name) + "_language"); string program_type = "default"; string program_name = name; if (lang == "Python2.7") { program_type = "python2.7"; } else if (lang == "Python3") { program_type = "python3.4"; } else if (lang == "Java7") { program_name += "." + conf_str(name + "_main_class"); program_type = "java7u76"; } else if (lang == "Java8") { program_name += "." + conf_str(name + "_main_class"); program_type = "java8u31"; } rpc.result_file_name = result_path + "/run_submission_program.txt"; rpc.input_file_name = input_file_name; rpc.output_file_name = output_file_name; rpc.error_file_name = "/dev/null"; rpc.limit = limit; rpc.type = program_type; rpc.set_argv(program_name.c_str(), NULL); RunResult res = run_program(rpc); if (res.type == RS_AC && res.exit_code != 0) { res.type = RS_RE; } return res; } void prepare_run_standard_program() { string data_path_std = data_path + "/std"; string work_path_std = work_path + "/std"; executef("cp %s %s", data_path_std.c_str(), work_path_std.c_str()); conf_add("std_language", "C++"); } RunResult run_standard_program( const string &input_file_name, const string &output_file_name, const RunLimit &limit, RunProgramConfig rpc = RunProgramConfig()) { rpc.result_file_name = result_path + "/run_standard_program.txt"; return run_submission_program( input_file_name, output_file_name, limit, "std", rpc); } /*======================== run End ==================== */ /*======================== compile ==================== */ bool is_illegal_keyword(const string &name) { if (name == "__asm" || name == "__asm__" || name == "asm") return true; return false; } bool has_illegal_keywords_in_file(const string &name) { FILE *f = fopen(name.c_str(), "r"); int c; string key; while ((c = fgetc(f)) != EOF) { if (('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '_') { if (key.size() < 20) key += c; else { if (is_illegal_keyword(key)) return true; key.erase(key.begin()); key += c; } } else { if (is_illegal_keyword(key)) return true; key.clear(); } } if (is_illegal_keyword(key)) return true; fclose(f); return false; } RunCompilerResult prepare_java_source(const string &name, const string &path = work_path) { FILE *f = fopen((path + "/" + name + ".code").c_str(), "r"); const int L = 1024; std::string s; char buf[L + 1]; int mode = 0; while (!feof(f)) { buf[fread(buf, 1, L, f)] = '\0'; for (char *p = buf; *p; p++) { s += *p; switch (mode) { case 0: switch (*p) { case '/': mode = 1; break; case '\'': mode = 5; break; case '\"': mode = 6; break; } break; case 1: switch (*p) { case '/': mode = 2; s.resize(s.length() - 2); break; case '*': mode = 3; s.resize(s.length() - 2); break; } break; case 2: s.resize(s.length() - 1); switch (*p) { case '\n': s += '\n'; mode = 0; break; } break; case 3: s.resize(s.length() - 1); switch (*p) { case '*': mode = 4; break; } break; case 4: s.resize(s.length() - 1); switch (*p) { case '/': s += ' '; mode = 0; break; } break; case 5: switch (*p) { case '\'': mode = 0; break; case '\\': mode = 7; break; } case 6: switch (*p) { case '\"': mode = 0; break; case '\\': mode = 8; break; } case 7: mode = 5; break; case 8: mode = 6; break; } } } bool valid[256]; fill(valid, valid + 256, false); for (int c = 'a'; c <= 'z'; c++) valid[c] = true; for (int c = 'A'; c <= 'Z'; c++) valid[c] = true; valid['.'] = true; valid['_'] = true; vector tokens; for (int p = 0, np = 0; p < (int)s.length(); p = np) { while (np < (int)s.length() && valid[(unsigned char)s[np]]) { np++; } if (np == p) { np++; } else { tokens.push_back(s.substr(p, np - p)); } } if (tokens.size() > 0 && tokens[0] == "package") { RunCompilerResult res; res.type = RS_WA; res.ust = -1; res.usm = -1; res.succeeded = false; res.info = "Please don't specify the package."; return res; } for (int i = 0; i + 1 < (int)tokens.size(); i++) { if (tokens[i] == "class") { if (tokens[i + 1].length() <= 100) { config[name + "_main_class"] = tokens[i + 1]; RunCompilerResult res; res.type = RS_AC; res.ust = 0; res.usm = 0; res.succeeded = true; return res; } else { RunCompilerResult res; res.type = RS_WA; res.ust = -1; res.usm = -1; res.succeeded = false; res.info = "The name of the main class is too long."; return res; } } } RunCompilerResult res; res.type = RS_WA; res.ust = -1; res.usm = -1; res.succeeded = false; res.info = "Can't find the main class."; return res; } RunCompilerResult compile_c(const string &name, const string &path = work_path) { return run_compiler(path.c_str(), "/usr/bin/gcc-4.8", "-o", name.c_str(), "-x", "c", (name + ".code").c_str(), "-lm", "-O2", "-DONLINE_JUDGE", NULL); } RunCompilerResult compile_pas(const string &name, const string &path = work_path) { return run_compiler(path.c_str(), "/usr/bin/fpc-2.6.2", (name + ".code").c_str(), "-O2", NULL); } RunCompilerResult compile_cpp(const string &name, const string &path = work_path) { return run_compiler(path.c_str(), "/usr/bin/g++-4.8", "-o", name.c_str(), "-x", "c++", (name + ".code").c_str(), "-lm", "-O2", "-DONLINE_JUDGE", NULL); } RunCompilerResult compile_cpp11(const string &name, const string &path = work_path) { return run_compiler(path.c_str(), "/usr/bin/g++-4.8", "-o", name.c_str(), "-x", "c++", (name + ".code").c_str(), "-lm", "-O2", "-DONLINE_JUDGE", "-std=c++11", NULL); } RunCompilerResult compile_python2_7(const string &name, const string &path = work_path) { return run_compiler(path.c_str(), "/usr/bin/python2.7", "-E", "-s", "-B", "-O", "-c", ("import py_compile\nimport sys\ntry:\n py_compile.compile('" + name + ".code'" + ", '" + name + "', doraise=True)\n sys.exit(0)\nexcept Exception as e:\n print e\n sys.exit(1)").c_str(), NULL); } RunCompilerResult compile_python3(const string &name, const string &path = work_path) { return run_compiler(path.c_str(), "/usr/bin/python3.4", "-I", "-B", "-O", "-c", ("import py_compile\nimport sys\ntry:\n py_compile.compile('" + name + ".code'" + ", '" + name + "', doraise=True)\n sys.exit(0)\nexcept Exception as e:\n print(e)\n sys.exit(1)").c_str(), NULL); } RunCompilerResult compile_java7(const string &name, const string &path = work_path) { RunCompilerResult ret = prepare_java_source(name, path); if (!ret.succeeded) return ret; string main_class = conf_str(name + "_main_class"); executef("rm %s/%s -rf 2>/dev/null; mkdir %s/%s", path.c_str(), name.c_str(), path.c_str(), name.c_str()); executef("echo package %s\\; | cat - %s/%s.code >%s/%s/%s.java", name.c_str(), path.c_str(), name.c_str(), path.c_str(), name.c_str(), main_class.c_str()); return run_compiler((path + "/" + name).c_str(), (main_path + "/run/runtime/jdk1.7.0_76/bin/javac").c_str(), (main_class + ".java").c_str(), NULL); } RunCompilerResult compile_java8(const string &name, const string &path = work_path) { RunCompilerResult ret = prepare_java_source(name, path); if (!ret.succeeded) return ret; string main_class = conf_str(name + "_main_class"); executef("rm %s/%s -rf 2>/dev/null; mkdir %s/%s", path.c_str(), name.c_str(), path.c_str(), name.c_str()); executef("echo package %s\\; | cat - %s/%s.code >%s/%s/%s.java", name.c_str(), path.c_str(), name.c_str(), path.c_str(), name.c_str(), main_class.c_str()); return run_compiler((path + "/" + name).c_str(), (main_path + "/run/runtime/jdk1.8.0_31/bin/javac").c_str(), (main_class + ".java").c_str(), NULL); } RunCompilerResult compile(const char *name) { string lang = conf_str(string(name) + "_language"); if ((lang == "C++" || lang == "C++11" || lang == "C") && has_illegal_keywords_in_file(work_path + "/" + name + ".code")) { RunCompilerResult res; res.type = RS_DGS; res.ust = -1; res.usm = -1; res.succeeded = false; res.info = "Compile Failed"; return res; } if (lang == "C++") { return compile_cpp(name); } if (lang == "C++11") { return compile_cpp11(name); } if (lang == "Python2.7") { return compile_python2_7(name); } if (lang == "Python3") { return compile_python3(name); } if (lang == "Java7") { return compile_java7(name); } if (lang == "Java8") { return compile_java8(name); } if (lang == "C") { return compile_c(name); } if (lang == "Pascal") { return compile_pas(name); } RunCompilerResult res = RunCompilerResult::failed_result(); res.info = "This language is not supported yet."; return res; } RunCompilerResult compile_c_with_implementer(const string &name, const string &path = work_path) { return run_compiler(path.c_str(), "/usr/bin/gcc-4.8", "-o", name.c_str(), "implementer.c", "-x", "c", (name + ".code").c_str(), "-lm", "-O2", "-DONLINE_JUDGE", NULL); } RunCompilerResult compile_pas_with_implementer(const string &name, const string &path = work_path) { executef("cp %s %s", (path + "/" + name + ".code").c_str(), (path + "/" + conf_str(name + "_unit_name") + ".pas").c_str()); return run_compiler(path.c_str(), "/usr/bin/fpc-2.6.2", "implementer.pas", ("-o" + name).c_str(), "-O2", NULL); } RunCompilerResult compile_cpp_with_implementer(const string &name, const string &path = work_path) { return run_compiler(path.c_str(), "/usr/bin/g++-4.8", "-o", name.c_str(), "implementer.cpp", "-x", "c++", (name + ".code").c_str(), "-lm", "-O2", "-DONLINE_JUDGE", NULL); } RunCompilerResult compile_cpp11_with_implementer(const string &name, const string &path = work_path) { return run_compiler(path.c_str(), "/usr/bin/g++-4.8", "-o", name.c_str(), "implementer.cpp", "-x", "c++", (name + ".code").c_str(), "-lm", "-O2", "-DONLINE_JUDGE", "-std=c++11", NULL); } /* RunCompilerResult compile_python2_7(const string &name, const string &path = work_path) { return run_compiler(path.c_str(), "/usr/bin/python2.7", "-E", "-s", "-B", "-O", "-c", ("import py_compile\nimport sys\ntry:\n py_compile.compile('" + name + ".code'" + ", '" + name + "', doraise=True)\n sys.exit(0)\nexcept Exception as e:\n print e\n sys.exit(1)").c_str(), NULL); } RunCompilerResult compile_python3(const string &name, const string &path = work_path) { return run_compiler(path.c_str(), "/usr/bin/python3.4", "-I", "-B", "-O", "-c", ("import py_compile\nimport sys\ntry:\n py_compile.compile('" + name + ".code'" + ", '" + name + "', doraise=True)\n sys.exit(0)\nexcept Exception as e:\n print(e)\n sys.exit(1)").c_str(), NULL); } */ RunCompilerResult compile_with_implementer(const char *name) { string lang = conf_str(string(name) + "_language"); if (has_illegal_keywords_in_file(work_path + "/" + name + ".code")) { RunCompilerResult res; res.type = RS_DGS; res.ust = -1; res.usm = -1; res.succeeded = false; res.info = "Compile Failed"; return res; } if (lang == "C++") { return compile_cpp_with_implementer(name); } if (lang == "C++11") { return compile_cpp11_with_implementer(name); } if (lang == "C") { return compile_c_with_implementer(name); } if (lang == "Pascal") { return compile_pas_with_implementer(name); } RunCompilerResult res = RunCompilerResult::failed_result(); res.info = "This language is not supported yet."; return res; } /*====================== compile End ================== */ /*====================== test ================== */ struct TestPointConfig { int submit_answer; int validate_input_before_test; string input_file_name; string output_file_name; string answer_file_name; TestPointConfig() : submit_answer(-1), validate_input_before_test(-1) { } void auto_complete(int num) { if (submit_answer == -1) { submit_answer = conf_is("submit_answer", "on"); } if (validate_input_before_test == -1) { validate_input_before_test = conf_is("validate_input_before_test", "on"); } if (input_file_name.empty()) { input_file_name = data_path + "/" + conf_input_file_name(num); } if (output_file_name.empty()) { output_file_name = work_path + "/" + conf_output_file_name(num); } if (answer_file_name.empty()) { answer_file_name = data_path + "/" + conf_output_file_name(num); } } }; PointInfo test_point(const string &name, const int &num, TestPointConfig tpc = TestPointConfig()) { tpc.auto_complete(num); if (tpc.validate_input_before_test) { RunValidatorResult val_ret = run_validator( tpc.input_file_name, conf_run_limit("validator", 0, RL_VALIDATOR_DEFAULT), conf_str("validator")); if (val_ret.type != RS_AC) { return PointInfo(num, 0, -1, -1, "Validator " + info_str(val_ret.type), file_preview(tpc.input_file_name), "", ""); } else if (!val_ret.succeeded) { return PointInfo(num, 0, -1, -1, "Invalid Input", file_preview(tpc.input_file_name), "", val_ret.info); } } RunResult pro_ret; if (!tpc.submit_answer) { pro_ret = run_submission_program( tpc.input_file_name.c_str(), tpc.output_file_name.c_str(), conf_run_limit(num, RL_DEFAULT), name); if (conf_has("token")) { file_hide_token(tpc.output_file_name, conf_str("token", "")); } if (pro_ret.type != RS_AC) { return PointInfo(num, 0, -1, -1, info_str(pro_ret.type), file_preview(tpc.input_file_name), file_preview(tpc.output_file_name), ""); } } else { pro_ret.type = RS_AC; pro_ret.ust = -1; pro_ret.usm = -1; pro_ret.exit_code = 0; } RunCheckerResult chk_ret = run_checker( conf_run_limit("checker", num, RL_CHECKER_DEFAULT), conf_str("checker"), tpc.input_file_name, tpc.output_file_name, tpc.answer_file_name); if (chk_ret.type != RS_AC) { return PointInfo(num, 0, -1, -1, "Checker " + info_str(chk_ret.type), file_preview(tpc.input_file_name), file_preview(tpc.output_file_name), ""); } string info; if (chk_ret.scr == 0) { info = "Wrong Answer"; } else if (chk_ret.scr == 100) { info = "Accepted"; } else { info = "Acceptable Answer"; } return PointInfo(num, chk_ret.scr, pro_ret.ust, pro_ret.usm, info, file_preview(tpc.input_file_name), file_preview(tpc.output_file_name), chk_ret.info); } PointInfo test_hack_point(const string &name, TestPointConfig tpc) { tpc.submit_answer = false; tpc.validate_input_before_test = false; tpc.auto_complete(0); RunValidatorResult val_ret = run_validator( tpc.input_file_name, conf_run_limit("validator", 0, RL_VALIDATOR_DEFAULT), conf_str("validator")); if (val_ret.type != RS_AC) { return PointInfo(0, 0, -1, -1, "Validator " + info_str(val_ret.type), file_preview(tpc.input_file_name), "", ""); } else if (!val_ret.succeeded) { return PointInfo(0, 0, -1, -1, "Invalid Input", file_preview(tpc.input_file_name), "", val_ret.info); } RunResult std_ret = run_standard_program( tpc.input_file_name, tpc.answer_file_name, conf_run_limit(0, RL_DEFAULT)); if (std_ret.type != RS_AC) { return PointInfo(0, 0, -1, -1, "Standard Program " + info_str(std_ret.type), file_preview(tpc.input_file_name), "", ""); } if (conf_has("token")) { file_hide_token(tpc.answer_file_name, conf_str("token", "")); } PointInfo po = test_point(name, 0, tpc); po.scr = po.scr != 100; return po; } CustomTestInfo ordinary_custom_test(const string &name) { RunLimit lim = conf_run_limit(0, RL_DEFAULT); lim.time += 2; string input_file_name = work_path + "/input.txt"; string output_file_name = work_path + "/output.txt"; RunResult pro_ret = run_submission_program( input_file_name, output_file_name, lim, name); if (conf_has("token")) { file_hide_token(output_file_name, conf_str("token", "")); } string info; if (pro_ret.type == RS_AC) { info = "Success"; } else { info = info_str(pro_ret.type); } string exp; if (pro_ret.type == RS_TLE) { exp = "

[time limit: " + vtos(lim.time) + "s]

"; } return CustomTestInfo(pro_ret.ust, pro_ret.usm, info, exp, file_preview(output_file_name, 2048)); } int scale_score(int scr100, int full) { return scr100 * full / 100; } /*====================== test End ================== */ /*======================= conf init =================== */ void main_judger_init(int argc, char **argv) { main_path = UOJ_WORK_PATH; work_path = main_path + "/work"; result_path = string(UOJ_RESULT_PATH); load_config(work_path + "/submission.conf"); problem_id = conf_int("problem_id"); data_path = string(UOJ_DATA_PATH) + "/" + conf_str("problem_id"); load_config(data_path + "/problem.conf"); executef("cp %s/require/* %s 2>/dev/null", data_path.c_str(), work_path.c_str()); if (conf_is("use_builtin_judger", "on")) { config["judger"] = string(UOJ_WORK_PATH) + "/builtin/judger/judger"; } else { config["judger"] = data_path + "/judger"; } } void judger_init(int argc, char **argv) { if (argc != 5) { exit(1); } main_path = argv[1]; work_path = argv[2]; result_path = argv[3]; data_path = argv[4]; load_config(work_path + "/submission.conf"); problem_id = conf_int("problem_id"); load_config(data_path + "/problem.conf"); if (config.count("use_builtin_checker")) { config["checker"] = main_path + "/builtin/checker/" + config["use_builtin_checker"]; } else { config["checker"] = data_path + "/chk"; } config["validator"] = data_path + "/val"; } /*===================== conf init End ================= */