products/sources/formale Sprachen/C/Firefox/config/   (Wiener Entwicklungsmethode ©)  Datei vom 10.2.2025 mit Größe 11 kB image not shown  

Quelle  check_macroassembler_style.py   Sprache: Python

 
# vim: set ts=8 sts=4 et sw=4 tw=99:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# ----------------------------------------------------------------------------
# This script checks that SpiderMonkey MacroAssembler methods are properly
# annotated.
#
# The MacroAssembler has one interface for all platforms, but it might have one
# definition per platform. The code of the MacroAssembler use a macro to
# annotate the method declarations, in order to delete the function if it is not
# present on the current platform, and also to locate the files in which the
# methods are defined.
#
# This script scans the MacroAssembler.h header, for method declarations.
# It also scans MacroAssembler-/arch/.cpp, MacroAssembler-/arch/-inl.h, and
# MacroAssembler-inl.h for method definitions. The result of both scans are
# uniformized, and compared, to determine if the MacroAssembler.h header as
# proper methods annotations.
# ----------------------------------------------------------------------------

import difflib
import os
import re
import sys

architecture_independent = set(["generic"])
all_unsupported_architectures_names = set(["mips32""mips64""mips_shared"])
all_architecture_names = set(
    ["x86""x64""arm""arm64""loong64""riscv64""wasm32"]
)
all_shared_architecture_names = set(
    ["x86_shared""arm""arm64""loong64""riscv64""wasm32"]
)

reBeforeArg = r"(?<=[(,\s])"
reArgType = r"(?P[\w\s:*&<>]+)"
reArgName = r"(?P\s\w+)"
reArgDefault = r"(?P(?:\s=(?:(?:\s[\w:]+\(\))|[^,)]+))?)"
reAfterArg = "(?=[,)])"
reMatchArg = re.compile(reBeforeArg + reArgType + reArgName + reArgDefault + reAfterArg)


def get_normalized_signatures(signature, fileAnnot=None):
    # Remove static
    signature = signature.replace("static""")
    # Remove semicolon.
    signature = signature.replace(";"" ")
    # Normalize spaces.
    signature = re.sub(r"\s+"" ", signature).strip()
    # Remove new-line induced spaces after opening braces.
    signature = re.sub(r"\(\s+""(", signature).strip()
    # Match arguments, and keep only the type.
    signature = reMatchArg.sub(r"\g", signature)
    # Remove class name
    signature = signature.replace("MacroAssembler::""")

    # Extract list of architectures
    archs = ["generic"]
    if fileAnnot:
        archs = [fileAnnot["arch"]]

    if "DEFINED_ON(" in signature:
        archs = re.sub(
            r".*DEFINED_ON\((?P[^()]*)\).*", r"\g", signature
        ).split(",")
        archs = [a.strip() for a in archs]
        signature = re.sub(r"\s+DEFINED_ON\([^()]*\)""", signature)

    elif "PER_ARCH" in signature:
        archs = all_architecture_names
        signature = re.sub(r"\s+PER_ARCH""", signature)

    elif "PER_SHARED_ARCH" in signature:
        archs = all_shared_architecture_names
        signature = re.sub(r"\s+PER_SHARED_ARCH""", signature)

    elif "OOL_IN_HEADER" in signature:
        assert archs == ["generic"]
        signature = re.sub(r"\s+OOL_IN_HEADER""", signature)

    else:
        # No signature annotation, the list of architectures remains unchanged.
        pass

    # Extract inline annotation
    inline = False
    if fileAnnot:
        inline = fileAnnot["inline"]

    if "inline " in signature:
        signature = re.sub(r"inline\s+""", signature)
        inline = True

    inlinePrefx = ""
    if inline:
        inlinePrefx = "inline "
    signatures = [{"arch": a, "sig": inlinePrefx + signature} for a in archs]

    return signatures


file_suffixes = set(
    [
        a.replace("_""-")
        for a in all_architecture_names.union(all_shared_architecture_names).union(
            all_unsupported_architectures_names
        )
    ]
)


def get_file_annotation(filename):
    origFilename = filename
    filename = filename.split("/")[-1]

    inline = False
    if filename.endswith(".cpp"):
        filename = filename[: -len(".cpp")]
    elif filename.endswith("-inl.h"):
        inline = True
        filename = filename[: -len("-inl.h")]
    elif filename.endswith(".h"):
        # This allows the definitions block in MacroAssembler.h to be
        # style-checked.
        inline = True
        filename = filename[: -len(".h")]
    else:
        raise Exception("unknown file name", origFilename)

    arch = "generic"
    for suffix in file_suffixes:
        if filename == "MacroAssembler-" + suffix:
            arch = suffix
            break

    return {"inline": inline, "arch": arch.replace("-""_")}


def get_macroassembler_definitions(filename):
    try:
        fileAnnot = get_file_annotation(filename)
    except Exception:
        return []

    style_section = False
    lines = ""
    signatures = []
    with open(filename, encoding="utf-8"as f:
        for line in f:
            if "//{{{ check_macroassembler_style" in line:
                if style_section:
                    raise "check_macroassembler_style section already opened."
                style_section = True
                braces_depth = 0
            elif "//}}} check_macroassembler_style" in line:
                style_section = False
            if not style_section:
                continue

            # Ignore preprocessor directives.
            if line.startswith("#"):
                continue

            # Remove comments from the processed line.
            line = re.sub(r"//.*""", line)

            # Locate and count curly braces.
            open_curly_brace = line.find("{")
            was_braces_depth = braces_depth
            braces_depth = braces_depth + line.count("{") - line.count("}")

            # Raise an error if the check_macroassembler_style macro is used
            # across namespaces / classes scopes.
            if braces_depth < 0:
                raise "check_macroassembler_style annotations are not well scoped."

            # If the current line contains an opening curly brace, check if
            # this line combines with the previous one can be identified as a
            # MacroAssembler function signature.
            if open_curly_brace != -1 and was_braces_depth == 0:
                lines = lines + line[:open_curly_brace]
                if "MacroAssembler::" in lines:
                    signatures.extend(get_normalized_signatures(lines, fileAnnot))
                lines = ""
                continue

            # We do not aggregate any lines if we are scanning lines which are
            # in-between a set of curly braces.
            if braces_depth > 0:
                continue
            if was_braces_depth != 0:
                line = line[line.rfind("}") + 1 :]

            # This logic is used to remove template instantiation, static
            # variable definitions and function declaration from the next
            # function definition.
            last_semi_colon = line.rfind(";")
            if last_semi_colon != -1:
                lines = ""
                line = line[last_semi_colon + 1 :]

            # Aggregate lines of non-braced text, which corresponds to the space
            # where we are expecting to find function definitions.
            lines = lines + line

    return signatures


def get_macroassembler_declaration(filename):
    style_section = False
    lines = ""
    signatures = []
    with open(filename, encoding="utf-8"as f:
        for line in f:
            if "//{{{ check_macroassembler_decl_style" in line:
                style_section = True
            elif "//}}} check_macroassembler_decl_style" in line:
                style_section = False
            if not style_section:
                continue

            # Ignore preprocessor directives.
            if line.startswith("#"):
                continue

            line = re.sub(r"//.*""", line)
            if len(line.strip()) == 0 or "public:" in line or "private:" in line:
                lines = ""
                continue

            lines = lines + line

            # Continue until we have a complete declaration
            if ";" not in lines:
                continue

            # Skip member declarations: which are lines ending with a
            # semi-colon without any list of arguments.
            if ")" not in lines:
                lines = ""
                continue

            signatures.extend(get_normalized_signatures(lines))
            lines = ""

    return signatures


def append_signatures(d, sigs):
    for s in sigs:
        if s["sig"not in d:
            d[s["sig"]] = []
        d[s["sig"]].append(s["arch"])
    return d


def generate_file_content(signatures):
    output = []
    for s in sorted(signatures.keys()):
        archs = set(sorted(signatures[s]))
        archs -= all_unsupported_architectures_names
        if len(archs.symmetric_difference(architecture_independent)) == 0:
            output.append(s + ";\n")
            if s.startswith("inline"):
                # TODO, bug 1432600: This is mistaken for OOL_IN_HEADER
                # functions.  (Such annotation is already removed by the time
                # this function sees the signature here.)
                output.append(" is defined in MacroAssembler-inl.h\n")
            else:
                output.append(" is defined in MacroAssembler.cpp\n")
        else:
            if len(archs.symmetric_difference(all_architecture_names)) == 0:
                output.append(s + " PER_ARCH;\n")
            elif len(archs.symmetric_difference(all_shared_architecture_names)) == 0:
                output.append(s + " PER_SHARED_ARCH;\n")
            else:
                output.append(s + " DEFINED_ON(" + ", ".join(sorted(archs)) + ");\n")
            for a in sorted(archs):
                a = a.replace("_""-")
                masm = "%s/MacroAssembler-%s" % (a, a)
                if s.startswith("inline"):
                    output.append(" is defined in %s-inl.h\n" % masm)
                else:
                    output.append(" is defined in %s.cpp\n" % masm)
    return output


def check_style():
    # We read from the header file the signature of each function.
    decls = dict()  # type: dict(signature => ['x86', 'x64'])

    # We infer from each file the signature of each MacroAssembler function.
    defs = dict()  # type: dict(signature => ['x86', 'x64'])

    root_dir = os.path.join("js""src""jit")
    for dirpath, dirnames, filenames in os.walk(root_dir):
        for filename in filenames:
            if "MacroAssembler" not in filename:
                continue

            filepath = os.path.join(dirpath, filename).replace("\\""/")

            if filepath.endswith("MacroAssembler.h"):
                decls = append_signatures(
                    decls, get_macroassembler_declaration(filepath)
                )
            defs = append_signatures(defs, get_macroassembler_definitions(filepath))

    if not decls or not defs:
        raise Exception("Did not find any definitions or declarations")

    # Compare declarations and definitions output.
    difflines = difflib.unified_diff(
        generate_file_content(decls),
        generate_file_content(defs),
        fromfile="check_macroassembler_style.py declared syntax",
        tofile="check_macroassembler_style.py found definitions",
    )
    ok = True
    for diffline in difflines:
        ok = False
        print(diffline, end="")
    return ok


def main():
    ok = check_style()

    if ok:
        print("TEST-PASS | check_macroassembler_style.py | ok")
    else:
        print(
            "TEST-UNEXPECTED-FAIL | check_macroassembler_style.py | actual output does not match expected output; diff is above"  # noqa: E501
        )

    sys.exit(0 if ok else 1)


if __name__ == "__main__":
    main()

84%


¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Versionsinformation zu Columbo

Bemerkung:

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Anfrage:

Dauer der Verarbeitung:

Sekunden

sprechenden Kalenders