minprog / checks

check50 checks for the minor programming (proglab.nl)
0 stars 0 forks source link

rm main from student file #1

Open Jelleas opened 8 months ago

Jelleas commented 8 months ago

pycparser kan met een beetje "masseren" de C opdrachten parsen. Onderstaande vind de main functie in een C bestand.

import check50.internal
from pycparser import c_ast, parse_file, c_generator

def get_main(filename: str) -> c_ast.FuncDef | None:
    main = None
    class FuncDefVisitor(c_ast.NodeVisitor):
        def visit_FuncDef(self, node):
            if node.decl.name == "main":
                nonlocal main
                main = node

    fake_libc_include = check50.internal.check_dir.parent / "fake_libc_include"

    ast = parse_file(
        filename, 
        use_cpp=True,
        cpp_path='clang',
        cpp_args=[
            '-E', # preprocess using clang
            '-nostdinc', # strictly use fake libc
            '-D__attribute__(x)=', # pycparser does not support __attribute__, so delete
            f'-I{fake_libc_include}' # include fake libc (just typedefs and headers)
        ]
    )

    visitor = FuncDefVisitor()
    visitor.visit(ast)

    return main

Bijvoorbeeld

>>> print(get_main("functions.c").coord)
functions.c:8:5

fake_libc_include is nodig om libc te spoofen. In bovenstaande voorbeeld staat deze map direct naast de checks, vandaar check50.internal.check_dir.parent / "fake_libc_include"

Jelleas commented 8 months ago

Coord van laatste karakter is niet beschikbaar, alleen het begin van iedere ast-node. Dat maakt einde van de main functie lastig.

Jelleas commented 8 months ago

Wegschrijven via c_generator.CGenerator bijvoorbeeld met dit voorbeeld is niet zo handig. Dat schrijft ook gespoofde/gefakete includes mee.