#!/usr/bin/python3
# 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/.


from __future__ import print_function

import argparse
import re

from collections import defaultdict

parser = argparse.ArgumentParser(description="Process some integers.")
parser.add_argument("rootingHazards", nargs="?", default="rootingHazards.txt")
parser.add_argument("gcFunctions", nargs="?", default="gcFunctions.txt")
parser.add_argument("hazards", nargs="?", default="hazards.txt")
parser.add_argument("extra", nargs="?", default="unnecessary.txt")
parser.add_argument("refs", nargs="?", default="refs.txt")
args = parser.parse_args()

num_hazards = 0
num_refs = 0
num_missing = 0

try:
    with open(args.rootingHazards) as rootingHazards, open(
        args.hazards, "w"
    ) as hazards, open(args.extra, "w") as extra, open(args.refs, "w") as refs:
        current_gcFunction = None

        # Map from a GC function name to the list of hazards resulting from
        # that GC function
        hazardousGCFunctions = defaultdict(list)

        # List of tuples (gcFunction, index of hazard) used to maintain the
        # ordering of the hazards
        hazardOrder = []

        # Map from a hazardous GC function to the filename containing it.
        fileOfFunction = {}

        for line in rootingHazards:
            m = re.match(r"^Time: (.*)", line)
            mm = re.match(r"^Run on:", line)
            if m or mm:
                print(line, file=hazards)
                print(line, file=extra)
                print(line, file=refs)
                continue

            m = re.match(r"^Function.*has unnecessary root", line)
            if m:
                print(line, file=extra)
                continue

            m = re.match(r"^Function.*takes unsafe address of unrooted", line)
            if m:
                num_refs += 1
                print(line, file=refs)
                continue

            m = re.match(
                r"^Function.*has unrooted.*of type.*live across GC call '(.*?)' at (\S+):\d+$",
                line,
            )  # NOQA: E501
            if m:
                current_gcFunction = m.group(1)
                hazardousGCFunctions[current_gcFunction].append(line)
                hazardOrder.append(
                    (
                        current_gcFunction,
                        len(hazardousGCFunctions[current_gcFunction]) - 1,
                    )
                )
                num_hazards += 1
                fileOfFunction[current_gcFunction] = m.group(2)
                continue

            m = re.match(r"Function.*expected hazard.*but none were found", line)
            if m:
                num_missing += 1
                print(line + "\n", file=hazards)
                continue

            if current_gcFunction:
                if not line.strip():
                    # Blank line => end of this hazard
                    current_gcFunction = None
                else:
                    hazardousGCFunctions[current_gcFunction][-1] += line

        with open(args.gcFunctions) as gcFunctions:
            gcExplanations = {}  # gcFunction => stack showing why it can GC

            current_func = None
            explanation = None
            for line in gcFunctions:
                m = re.match(r"^GC Function: (.*)", line)
                if m:
                    if current_func:
                        gcExplanations[current_func] = explanation
                    current_func = None
                    if m.group(1) in hazardousGCFunctions:
                        current_func = m.group(1)
                        explanation = line
                elif current_func:
                    explanation += line
            if current_func:
                gcExplanations[current_func] = explanation

        for gcFunction, index in hazardOrder:
            gcHazards = hazardousGCFunctions[gcFunction]

            if gcFunction in gcExplanations:
                print(gcHazards[index] + gcExplanations[gcFunction], file=hazards)
            else:
                print(gcHazards[index], file=hazards)

except IOError as e:
    print("Failed: %s" % str(e))

print("Wrote %s" % args.hazards)
print("Wrote %s" % args.extra)
print("Wrote %s" % args.refs)
print(
    "Found %d hazards %d unsafe references %d missing"
    % (num_hazards, num_refs, num_missing)
)

#!/usr/bin/python3
# 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/.


from __future__ import print_function

import argparse
import re

from collections import defaultdict

parser = argparse.ArgumentParser(description="Process some integers.")
parser.add_argument("rootingHazards", nargs="?", default="rootingHazards.txt")
parser.add_argument("gcFunctions", nargs="?", default="gcFunctions.txt")
parser.add_argument("hazards", nargs="?", default="hazards.txt")
parser.add_argument("extra", nargs="?", default="unnecessary.txt")
parser.add_argument("refs", nargs="?", default="refs.txt")
args = parser.parse_args()

num_hazards = 0
num_refs = 0
num_missing = 0

try:
    with open(args.rootingHazards) as rootingHazards, open(
        args.hazards, "w"
    ) as hazards, open(args.extra, "w") as extra, open(args.refs, "w") as refs:
        current_gcFunction = None

        # Map from a GC function name to the list of hazards resulting from
        # that GC function
        hazardousGCFunctions = defaultdict(list)

        # List of tuples (gcFunction, index of hazard) used to maintain the
        # ordering of the hazards
        hazardOrder = []

        # Map from a hazardous GC function to the filename containing it.
        fileOfFunction = {}

        for line in rootingHazards:
            m = re.match(r"^Time: (.*)", line)
            mm = re.match(r"^Run on:", line)
            if m or mm:
                print(line, file=hazards)
                print(line, file=extra)
                print(line, file=refs)
                continue

            m = re.match(r"^Function.*has unnecessary root", line)
            if m:
                print(line, file=extra)
                continue

            m = re.match(r"^Function.*takes unsafe address of unrooted", line)
            if m:
                num_refs += 1
                print(line, file=refs)
                continue

            m = re.match(
                r"^Function.*has unrooted.*of type.*live across GC call '(.*?)' at (\S+):\d+$",
                line,
            )  # NOQA: E501
            if m:
                current_gcFunction = m.group(1)
                hazardousGCFunctions[current_gcFunction].append(line)
                hazardOrder.append(
                    (
                        current_gcFunction,
                        len(hazardousGCFunctions[current_gcFunction]) - 1,
                    )
                )
                num_hazards += 1
                fileOfFunction[current_gcFunction] = m.group(2)
                continue

            m = re.match(r"Function.*expected hazard.*but none were found", line)
            if m:
                num_missing += 1
                print(line + "\n", file=hazards)
                continue

            if current_gcFunction:
                if not line.strip():
                    # Blank line => end of this hazard
                    current_gcFunction = None
                else:
                    hazardousGCFunctions[current_gcFunction][-1] += line

        with open(args.gcFunctions) as gcFunctions:
            gcExplanations = {}  # gcFunction => stack showing why it can GC

            current_func = None
            explanation = None
            for line in gcFunctions:
                m = re.match(r"^GC Function: (.*)", line)
                if m:
                    if current_func:
                        gcExplanations[current_func] = explanation
                    current_func = None
                    if m.group(1) in hazardousGCFunctions:
                        current_func = m.group(1)
                        explanation = line
                elif current_func:
                    explanation += line
            if current_func:
                gcExplanations[current_func] = explanation

        for gcFunction, index in hazardOrder:
            gcHazards = hazardousGCFunctions[gcFunction]

            if gcFunction in gcExplanations:
                print(gcHazards[index] + gcExplanations[gcFunction], file=hazards)
            else:
                print(gcHazards[index], file=hazards)

except IOError as e:
    print("Failed: %s" % str(e))

print("Wrote %s" % args.hazards)
print("Wrote %s" % args.extra)
print("Wrote %s" % args.refs)
print(
    "Found %d hazards %d unsafe references %d missing"
    % (num_hazards, num_refs, num_missing)
)

#!/usr/bin/python3 # 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/. # Map from a GC function name to the list of hazards resulting from # that GC function # List of tuples (gcFunction, index of hazard) used to maintain the # ordering of the hazards # Map from a hazardous GC function to the filename containing it. # NOQA: E501 # Blank line => end of this hazard # gcFunction => stack showing why it can GC