text: #!/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)
  )
  