예제 #1
0
파일: NASM.py 프로젝트: crazydreamer/judge
    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')
예제 #2
0
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)
예제 #3
0
 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')
예제 #4
0
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
예제 #5
0
    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
예제 #6
0
    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
예제 #7
0
 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
예제 #8
0
    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()
예제 #9
0
 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?"
     )
예제 #10
0
    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
예제 #11
0
    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
예제 #12
0
    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
예제 #13
0
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)
예제 #14
0
 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
예제 #15
0
 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)
예제 #16
0
    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
예제 #17
0
 def handle_compile_error(self, output):
     raise CompileError(output)
예제 #18
0
    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
예제 #19
0
 def __init__(self, pos, msgs):
   CompileError.__init__(self, pos, "parse error")
   self.msgs = set(msgs)
예제 #20
0
 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)
예제 #21
0
 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)