def __init__(self, problem_id, source_code): super(Executor, self).__init__() source_code_file = self._file('%s.asm' % problem_id) with open(source_code_file, 'wb') as fo: fo.write(source_code) obj_file = self._file('%s.o' % problem_id) self._executable = output_file = self._file(str(problem_id)) nasm_process = subprocess.Popen([ env['runtime']['nasm'], '-f', 'elf32', source_code_file, '-o', obj_file ], stderr=subprocess.PIPE, cwd=self._dir) _, compile_error = nasm_process.communicate() if nasm_process.returncode != 0: raise CompileError(compile_error) if 'gcc' in env['runtime'] and source_code.startswith('; libc'): ld_process = subprocess.Popen( [env['runtime']['gcc'], '-m32', obj_file, '-o', output_file], stderr=subprocess.PIPE, cwd=self._dir) else: ld_process = subprocess.Popen([ env['runtime']['ld'], '-melf_i386', '-s', obj_file, '-o', output_file ], stderr=subprocess.PIPE, cwd=self._dir) _, link_error = ld_process.communicate() if ld_process.returncode != 0: raise CompileError(link_error) self.name = problem_id self.warning = ('%s\n%s' % (compile_error, link_error)).strip('\n')
def normalizeDeclSpecs(specs): # At most one storage-class specifier may be given in the declaration # specifiers in a declaration ($3.5.1). storageClassSpec = None typeSpec = None signSpec = None sizeSpec = None for spec in specs: if isinstance(spec, syntree.StorageClassSpec): if storageClassSpec is None: storageClassSpec = spec else: if type(storageClassSpec) is type(spec): raise CompileError(spec.pos, "duplicate %s" % spec) # XXX no str(spec) else: raise CompileError(spec.pos, "multiple storage classes in" " declaration specifiers") elif isinstance(spec, syntree.TypeSpec): if typeSpec is None: typeSpec = spec else: raise CompileError(spec.pos, "two or more data types in declaration" " specifiers") # XXX signSpec, sizeSpec not implemented return (storageClassSpec, typeSpec, signSpec, sizeSpec)
def __init__(self, problem_id, source_code): super(Executor, self).__init__() class_name = find_class(source_code) source_code_file = self._file('%s.java' % class_name.group(1)) try: with open(source_code_file, 'wb') as fo: fo.write(source_code) except IOError as e: if e.errno in (errno.ENAMETOOLONG, errno.ENOENT): raise CompileError( 'Why do you need a class name so long? ' 'As a judge, I sentence your code to death.') raise javac_args = [env['runtime'][self.JAVAC], source_code_file] javac_process = Popen(javac_args, stderr=PIPE, cwd=self._dir) _, compile_error = javac_process.communicate() if javac_process.returncode != 0: if 'is public, should be declared in a file named' in compile_error: raise CompileError( 'You are a troll. Trolls are not welcome. ' 'As a judge, I sentence your code to death.') raise CompileError(compile_error) self._class_name = class_name.group(1) self.warning = compile_error self.statefile = self._file('state')
def find_class(source): source = reinline_comment.sub('', restring.sub('', recomment.sub('', source))) class_name = reclass.search(source) if class_name is None: raise CompileError( 'No public class: your main class must be declared as a "public class"' ) package = repackage.search(source) if package: raise CompileError('Invalid package %s: do not declare package' % package.group(1)) return class_name
def __init__(self, problem_id, main_source, aux_sources=None): super(Executor, self).__init__() if not aux_sources: aux_sources = {} aux_sources[problem_id + '.cpp'] = main_source sources = [] for name, source in aux_sources.iteritems(): if '.' not in name: name += '.cpp' with open(self._file(name), 'wb') as fo: fo.write(source) sources.append(name) output_file = self._file('%s.exe' % problem_id) cl_args = ['cl', '-nologo'] + sources + [ '-W4', '-DONLINE_JUDGE', '-DWIN32', '-D_CRT_SECURE_NO_WARNINGS', '-Ox', '-link', '-stack:67108864', '-Fe%s' % output_file ] cl_process = subprocess.Popen(cl_args, stderr=subprocess.PIPE, executable=env['runtime']['cl.exe'], cwd=self._dir, env=VC_COMPILE) _, compile_error = cl_process.communicate() if cl_process.returncode != 0: raise CompileError(compile_error) self._executable = output_file self.name = problem_id self.warning = compile_error
def visitCallExpr(self, node, lvalue=False): """Generate code for a function call expression""" # The result of a call is not an lvalue if lvalue: return None # Allocate a temporary variable for the return value var = next(self.varGen) # Generate code to grab the function address funAddrVar = node.expr.accept(self, True) # Check for invalid functions # XXX This should be done in the type checker if funAddrVar is None: raise CompileError(node.expr.pos, "called object is not a function") # Generate code for the expressions used as function arguments, pushing the # actual arguments on the parameter stack. for expr in node.argExprs: argVar = expr.accept(self) self.code.append(PushParam(argVar)) # Generate the call instruction self.code.append(Call(var, funAddrVar)) # Clean up the stack self.code.append(PopParams(len(node.argExprs))) return var
def compile(self): compile_process = subprocess.Popen(self.get_compile_args(), stderr=subprocess.STDOUT, stdout=subprocess.PIPE, cwd=self._dir) compile_error = compile_process.communicate()[0] if compile_process.returncode != 0: raise CompileError(compile_error) self.warning = compile_error
def compile(self): process = self.get_compile_process() output = self.get_compile_output(process) if process.returncode != 0: raise CompileError(output) self.warning = output return self.get_compiled_file()
def find_cpp(): global executors for grader in ('CPP11', 'CPP0X', 'CPP'): if grader in executors: return grader raise CompileError( "Can't grade with generator. Why did I get this submission?" )
def __genLValue(self, expr, label): """Generate code to get an address from an expression, raising an error if the expression is not an lvalue.""" addrVar = expr.accept(self, True) if addrVar is None: raise CompileError(expr.pos, "lvalue required as %s" % label) return addrVar
def visitContinueStmt(self, node): """Generate code for a continue statement""" if not self.continues: raise CompileError(node.pos, "continue statement not within loop") # Jump to the last continue jump location self.code.append(Jump(self.continues[-1])) # This statement doesn't return return False
def visitBreakStmt(self, node): """Generate code for a break statement""" if not self.breaks: raise CompileError(node.pos, "break statement not within loop") # Jump to the last break jump location self.code.append(Jump(self.breaks[-1])) # This statement doesn't return return False
def mkFunDef(specs, declarator_, decls, stmt): """Return a function definition given a list of declaration specifiers, a declarator, a declaration list, and a compound statement.""" # Substitute K&R function declarators if isinstance(declarator_, syntree.KRFunDeclarator): # Set up the default parameters paramDict = dict([(id_.val, mkKRParamDecl(id_)) for id_ in declarator_.ids]) # Change the declaration for any parameters in the declaration list for decl in decls: # Declarations in the declaration list must also appear in the parameter # list for init in decl.inits: if not init.id in paramDict: raise CompileError(decl.pos, "declaration for parameter `%s', but no" " such parameter" % init.id) paramDict[init.id] = syntree.ParamDecl(init) # Get the parameters in the order specified in the parameter list params = [paramDict[id_.val] for id_ in declarator_.ids] # Replace the declarator with a regular function declarator declarator_ = syntree.FunDeclarator(declarator_.direct, params) # Handle declaration specifiers storageClassSpec, typeSpec, signSpec, sizeSpec = normalizeDeclSpecs(specs) # The storage class specifier can only be extern or static for functions, and # is extern by default. if storageClassSpec is None: storageClassSpec = syntree.ExternStorageClassSpec(None) elif type(storageClassSpec) not in (syntree.ExternStorageClassSpec, syntree.StaticStorageClassSpec): raise CompileError(storageClassSpec.pos, "function definition declared '%s'" % storageClassSpec) # XXX no str(storageClassSpec) # XXX typeSpec can't be array # XXX signSpec, sizeSpec unused declarator_.applySpecs(storageClassSpec, typeSpec) return syntree.FunDef(declarator_, stmt)
def __init__(self, problem_id, source_code): super(Executor, self).__init__() source_code_file = self._file('%s.cbl' % problem_id) with open(source_code_file, 'wb') as fo: fo.write(source_code) self._executable = self._file(str(problem_id)) cbl_args = [env['runtime']['cobc'], '-x', source_code_file] cbl_process = subprocess.Popen(cbl_args, stdout=subprocess.PIPE, cwd=self._dir) compile_error, _ = cbl_process.communicate() if cbl_process.returncode != 0: raise CompileError(compile_error) self.name = problem_id self.warning = compile_error if 'Warning:' in compile_error or 'Note:' in compile_error else None
def create_files(self, problem_id, source_code): source_code = deunicode(source_code) class_name = find_class(source_code) self._code = self._file('%s.java' % class_name.group(1)) try: with open(self._code, 'wb') as fo: fo.write(source_code) except IOError as e: if e.errno in (errno.ENAMETOOLONG, errno.ENOENT): raise CompileError( 'Why do you need a class name so long? ' 'As a judge, I sentence your code to death.') raise self._class_name = class_name.group(1)
def visitVarExpr(self, node, lvalue=False): """Generate code for a variable expression""" # Look up the variable binding varEnv = self.env.find(node.id) # Check for undefined variables # XXX This should be done before code generation if varEnv is None: raise CompileError(node.pos, "`%s' undeclared" % node.id) var = varEnv[node.id] if lvalue: # Generate a variable containing the address of the result addrVar = next(self.varGen) self.code.append(AddressOf(addrVar, var)) return addrVar else: return var
def handle_compile_error(self, output): raise CompileError(output)
def _begin_grading(self, problem_id, language, original_source, time_limit, memory_limit, short_circuit): """ Threaded callback for begin_grading. """ submission_id = self.current_submission print >> sys.stderr, '===========Started Grading: %s===========' % submission_id try: problem_root = get_problem_root(problem_id) if problem_root is None: print >> sys.stderr, 'Unsupported problem:', problem_id print>>sys.stderr, 'Please install watchdog so that the bridge can be notified of problems files' \ ' disappearing' self.packet_manager.internal_error_packet( dedent('''\ Unsupported problem: %s. Please install watchdog so that the bridge can be notified of problem files disappearing.''' ) % problem_id) return with open(os.path.join(problem_root, 'init.json'), 'r') as init_file: init_data = json.load(init_file) if isinstance(original_source, unicode): source_code = original_source.encode('utf-8') else: source_code = original_source try: # Launch an executor for the given language # The executor is responsible for writing source files and compiling (if applicable) if 'handler' in init_data: siggraders = ('C', 'CPP', 'CPP0X', 'CPP11', 'CPP14') for i in reversed(siggraders): if i in executors: siggrader = i break else: raise CompileError( "Can't signature grade. Why did I get this submission?" ) if language in siggraders: aux_sources = {} handler_data = init_data['handler'] entry_path = os.path.join(problem_root, handler_data['entry']) header_path = os.path.join(problem_root, handler_data['header']) if not os.path.exists(entry_path): raise IOError( 'entry path "%s" does not exist' % entry_path) if not os.path.exists(header_path): raise IOError( 'header path "%s" does not exist' % header_path) with open(entry_path, 'r') as entry_point: with open(header_path, 'r') as header: aux_sources[problem_id + '_submission'] = ( '#include "%s"\n#define main main_%s\n' % (handler_data['header'], str(uuid.uuid4()).replace( '-', ''))) + source_code aux_sources[handler_data[ 'header']] = header.read() entry = entry_point.read() # Compile as CPP11 regardless of what the submission language is executor = executors[siggrader].Executor( problem_id, entry, aux_sources=aux_sources, writable=handler_data.get('writable', (1, 2)), fds=handler_data.get('fds', None)) else: raise CompileError( 'no valid handler compiler exists') else: executor = executors[language].Executor( problem_id, source_code) except KeyError: raise NotImplementedError('unsupported language: ' + language) except CompileError as e: print 'Compile Error' print e.args[0] self.packet_manager.compile_error_packet(e.args[0]) return try: # Obtain the output correctness checker, e.g. standard or float checker_id = init_data.get('checker', 'standard') if isinstance(checker_id, dict): checker_params = checker_id.get('parameters', {}) checker_id = checker_id['name'] else: checker_params = {} if '.' in checker_id: module_path = os.path.join(problem_root, checker_id) if not os.path.exists(module_path): raise IOError( 'checker module path "%s" does not exist' % module_path) checker = load_module_from_file(module_path) checker_id = checker.__name__ else: checker = getattr(checkers, checker_id) except AttributeError: raise NotImplementedError('error loading checker') print >> sys.stderr, 'Using checker %s' % checker_id # Use a proxy to not expose init_data to all submethods def check_adapter(test_input, proc_output, judge_output, point_value): return checker.check(proc_output, judge_output, submission_source=source_code, judge_input=test_input, point_value=point_value, **checker_params) case = 1 if hasattr(executor, 'warning') and executor.warning: self.packet_manager.compile_message_packet( executor.warning) for result in self.run(executor, init_data, check_adapter, problem_id, time=time_limit, memory=memory_limit, short_circuit=short_circuit, source_code=original_source, interactive=('grader' in init_data)): print 'Test case %s' % case print '\t%f seconds (real)' % result.r_execution_time print '\t%f seconds (debugged)' % result.execution_time # print '\tDebugging took %.2f%% of the time' % \ # ((result.r_execution_time - result.execution_time) / result.r_execution_time * 100) print '\t%.2f mb (%s kb)' % (result.max_memory / 1024.0, result.max_memory) if result.result_flag == Result.AC: print '\tAccepted' else: execution_verdict = [] for flag in [ 'IR', 'WA', 'RTE', 'TLE', 'MLE', 'SC', 'IE' ]: if result.result_flag & getattr(Result, flag): execution_verdict.append('\t' + flag) print '\n'.join(execution_verdict) case += 1 except TerminateGrading: self.packet_manager.submission_terminated_packet() print >> sys.stderr, 'Forcefully terminating grading. Temporary files may not be deleted.' except: traceback.print_exc() self.packet_manager.internal_error_packet(traceback.format_exc()) finally: print >> sys.stderr, '===========Done Grading: %s===========' % submission_id self._terminate_grading = False self.current_submission_thread = None self.current_submission = None
def __init__(self, pos, msgs): CompileError.__init__(self, pos, "parse error") self.msgs = set(msgs)
def handle_compile_error(self, output): if 'is public, should be declared in a file named' in output: raise CompileError('You are a troll. Trolls are not welcome. ' 'As a judge, I sentence your code to death.') raise CompileError(output)
def __init__(self, problem_id, source_code): if source_code.count('[') != source_code.count(']'): raise CompileError('Unmatched brackets') code = template % (''.join( itertools.imap(trans.get, source_code, itertools.repeat('')))) super(Executor, self).__init__(problem_id, code)