mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
1cc8c2c20c
Remove code in revng.cli.model_dump and override_by_name that was used when the model had tags. The code subclassed the default pyYAML loader to ignore unknown tags to allow reading the model data easily. Since the model no longer has tags this code is dead and can be removed.
148 lines
5.0 KiB
Python
148 lines
5.0 KiB
Python
#
|
|
# This file is distributed under the MIT License. See LICENSE.md for details.
|
|
#
|
|
|
|
import sys
|
|
from shutil import copyfileobj
|
|
from tempfile import NamedTemporaryFile
|
|
|
|
import yaml
|
|
|
|
from .commands_registry import Command, Options, commands_registry
|
|
from .revng import run_revng_command
|
|
from .support import log_error
|
|
|
|
|
|
class ModelOverrideByName(Command):
|
|
def __init__(self):
|
|
super().__init__(("model", "override-by-name"), "Override parts of the model")
|
|
|
|
def register_arguments(self, parser):
|
|
parser.add_argument("input_model_path", default="", help="Input model (can be IR)")
|
|
parser.add_argument("override_model_path", default="", help="Override model")
|
|
parser.add_argument(
|
|
"-o",
|
|
metavar="OUTPUT",
|
|
dest="output",
|
|
type=str,
|
|
default="/dev/stdout",
|
|
help="Output path",
|
|
)
|
|
|
|
def log(self, message):
|
|
if self.verbose:
|
|
sys.stderr.write(message + "\n")
|
|
|
|
def run(self, options: Options):
|
|
if options.remaining_args:
|
|
log_error("Unknown arguments passed in")
|
|
return 1
|
|
|
|
args = options.parsed_args
|
|
|
|
self.verbose = args.verbose
|
|
|
|
def temporary_file(suffix="", mode="w+"):
|
|
return NamedTemporaryFile(suffix=suffix, mode=mode, delete=not options.keep_temporaries)
|
|
|
|
with open(args.input_model_path, "rb") as input_file, temporary_file(
|
|
mode="wb+"
|
|
) as saved_file, temporary_file(suffix=".yml") as model_file, open(
|
|
args.override_model_path
|
|
) as override_file, temporary_file(
|
|
suffix=".yml"
|
|
) as patched_file, temporary_file(
|
|
suffix=".yml.diff"
|
|
) as patch_file, temporary_file(
|
|
suffix=".yml"
|
|
) as patched_model_file:
|
|
|
|
# Copy so we can work with stdin too
|
|
copyfileobj(input_file, saved_file)
|
|
saved_file.flush()
|
|
|
|
# Check if it's YAML
|
|
saved_file.seek(0)
|
|
input_is_yaml = saved_file.read(3) == "---"
|
|
|
|
# Extract model, if necessary
|
|
result = run_revng_command(
|
|
["model", "opt", "-Y", saved_file.name, "-o", model_file.name], options
|
|
)
|
|
if result != 0:
|
|
return result
|
|
|
|
self.log("Loading the base model")
|
|
base_model = yaml.load(model_file, Loader=yaml.SafeLoader)
|
|
self.log("Loading the override model")
|
|
override_model = yaml.load(override_file, Loader=yaml.SafeLoader)
|
|
|
|
self.log("Importing Entry and OriginalName")
|
|
for function_to_override in override_model["Functions"]:
|
|
function_name = function_to_override["OriginalName"]
|
|
|
|
if not function_name:
|
|
self.log("A function is missing OriginalName")
|
|
return 1
|
|
|
|
for base_function in base_model["Functions"]:
|
|
if base_function["OriginalName"] == function_name:
|
|
function_to_override["Entry"] = base_function["Entry"]
|
|
function_to_override["CustomName"] = base_function["CustomName"]
|
|
|
|
self.log("Saving patched override file")
|
|
patched_file.write("---\n")
|
|
yaml.dump(override_model, stream=patched_file)
|
|
patched_file.write("...\n")
|
|
patched_file.flush()
|
|
|
|
self.log("Compute diff between patched override file and base model")
|
|
result = run_revng_command(
|
|
["model", "diff", model_file.name, patched_file.name, "-o", patch_file.name],
|
|
options,
|
|
)
|
|
|
|
if result not in [0, 1]:
|
|
return result
|
|
|
|
self.log("Loading the patch file")
|
|
with open(patch_file.name) as loaded_patch_file:
|
|
patch = yaml.load(stream=loaded_patch_file, Loader=yaml.SafeLoader)
|
|
|
|
self.log("Removing all removals from the patch file")
|
|
patch["Changes"] = [
|
|
change
|
|
for change in patch["Changes"]
|
|
if ("Add" in change and change["Add"] not in ["", "Invalid", ":Invalid"])
|
|
]
|
|
|
|
self.log("Saving the patched patch file")
|
|
with open(patch_file.name, "wt") as saved_patch_file:
|
|
yaml.dump(patch, stream=saved_patch_file)
|
|
|
|
self.log("Applying the patched patch to the base model")
|
|
|
|
if input_is_yaml:
|
|
patched_model_path = args.output
|
|
else:
|
|
patched_model_path = patched_model_file.name
|
|
|
|
result = run_revng_command(
|
|
["model", "apply", model_file.name, patch_file.name, "-o", patched_model_path],
|
|
options,
|
|
)
|
|
|
|
if result != 0:
|
|
return result
|
|
|
|
if not input_is_yaml:
|
|
result = run_revng_command(
|
|
["model", "inject", patched_model_path, saved_file.name, "-o", args.output],
|
|
options,
|
|
)
|
|
|
|
return result
|
|
|
|
|
|
commands_registry.register_command(ModelOverrideByName())
|