def METHOD_NAME(self, filename):
    """Parse a file and save its output"""
    cmd = self.options.cpp
    # Legacy behaviour is to implicitly undefine '__GNUC__'
    # Continue doing this, unless user explicitly requested to allow it.
    if self.options.allow_gnu_c:
        # New behaviour. No implicit override.
        # (currently NOT enabled by default yet)
        pass
    else:
        # Legacy behaviour. Add an implicit override.
        # (currently the default)
        cmd += " -U __GNUC__"
    cmd += " -dD"
    for undefine in self.options.cpp_undefines:
        cmd += " -U%s" % undefine
    # This fixes Issue #6 where OS X 10.6+ adds a C extension that breaks
    # the parser.  Blocks shouldn't be needed for ctypesgen support anyway.
    if IS_MAC:
        cmd += " -U __BLOCKS__"
    for path in self.options.include_search_paths:
        cmd += ' -I"%s"' % path
    for define in self.defines + self.options.cpp_defines:
        cmd += ' "-D%s"' % define
    cmd += ' "' + filename + '"'
    self.cparser.handle_status(cmd)
    if IS_WINDOWS:
        cmd = ["sh.exe", "-c", cmd]
    pp = subprocess.Popen(
        cmd,
        shell=True,
        universal_newlines=False,  # binary
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )
    ppout_data, pperr_data = pp.communicate()
    try:
        ppout = ppout_data.decode("utf-8")
    except UnicodeError:
        if IS_MAC:
            ppout = ppout_data.decode("utf-8", errors="replace")
        else:
            raise UnicodeError
    pperr = pperr_data.decode("utf-8")
    if IS_WINDOWS:
        ppout = ppout.replace("\r\n", "\n")
        pperr = pperr.replace("\r\n", "\n")
    for line in pperr.split("\n"):
        if line:
            self.cparser.handle_pp_error(line)
    # We separate lines to two groups: directives and c-source.  Note that
    # #pragma directives actually belong to the source category for this.
    # This is necessary because some source files intermix preprocessor
    # directives with source--this is not tolerated by ctypesgen's single
    # grammar.
    # We put all the source lines first, then all the #define lines.
    source_lines = []
    define_lines = []
    first_token_reg = re.compile(r"^#\s*([^ ]+)($|\s)")
    for line in ppout.split("\n"):
        line += "\n"
        search = first_token_reg.match(line)
        hash_token = search.group(1) if search else None
        if (not hash_token) or hash_token == "pragma":
            source_lines.append(line)
            define_lines.append("\n")
        elif hash_token.isdigit():
            # Line number information has to go with both groups
            source_lines.append(line)
            define_lines.append(line)
        else:  # hash_token in ("define", "undef"):
            source_lines.append("\n")
            define_lines.append(line)
    text = "".join(source_lines + define_lines)
    if self.options.save_preprocessed_headers:
        self.cparser.handle_status(
            "Saving preprocessed headers to %s." % self.options.save_preprocessed_headers
        )
        try:
            with open(self.options.save_preprocessed_headers, "w") as f:
                f.write(text)
        except IOError:
            self.cparser.handle_error("Couldn't save headers.")
    self.lexer.input(text)
    self.output = []
    try:
        while True:
            token = self.lexer.token()
            if token is not None:
                self.output.append(token)
            else:
                break
    except LexError as e:
        self.cparser.handle_error("{}; {}".format(e, e.text.partition("\n")[0]), filename, 0)