Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/art/art/runtime/interpreter/mterp/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 6 kB image not shown  

Quelle  gen_mterp.py

  Sprache: Python
 

#!/usr/bin/env python3
#
# Copyright (C) 2016 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from io import StringIO
from pathlib import Path
from typing import List, Optional, Any
import os
import re
import sys

SCRIPT_DIR = Path(os.path.dirname(sys.argv[0]))
# This file is included verbatim at the start of the in-memory python script.
SCRIPT_SETUP_CODE = SCRIPT_DIR / "common/gen_setup.py"
INTERP_DEFS_FILE = SCRIPT_DIR / "../../../libdexfile/dex/dex_instruction_list.h"
NUM_OPCODES = 256

# Extract an ordered list of instructions from the VM sources.  We use the
# "goto table" definition macro, which has exactly NUM_OPCODES entries.
def getOpcodeList():
  opcodes: List[str] = []
  opcode_fp = open(INTERP_DEFS_FILE)
  opcode_re = re.compile(r"^\s*V\((....), (\w+),.*", re.DOTALL)
  for line in opcode_fp:
    match = opcode_re.match(line)
    if not match:
      continue
    opcodes.append("op_" + match.group(2).lower())
  opcode_fp.close()

  if len(opcodes) != NUM_OPCODES:
    print("ERROR: found ", len(opcodes), " opcodes in Interp.h (expected ", NUM_OPCODES, ")")
    raise SyntaxError("bad opcode count")
  return opcodes

# All lines must follow this generic pattern. Indentation is meaningfull.
line_re = re.compile(r"(?:%| |)(?P<indent>\s*)(?P<code>.*?)\s*")

# The following lines must be followed by increased indentation.
indent_re = [
  re.compile(r"%\s*(?P<name>\w*).*:\s*(?:#.*)?"),
  re.compile(r"\s*(?P<name>\.macro|\.if|\.ifnc|\.else|\.elseif)\b.*"),
  re.compile(r"\s*(?P<name>OAT_ENTRY|ENTRY|DEFINE_FUNCTION|NAME_START).*"),
]

# Exceptions. The following lines will just use the current indentation.
automatic_indent_re = {
  re.compile(r"#(\w)+.*"),    # C++ style preprocessor.
  re.compile(r"[^% ]*:\s*"),  # Assembly label.
}

# Finds variable references in text: $foo or ${foo}
variable_re = re.compile(r'''
  (?<!\$)        # Must not be preceded by another $.
  \$             # Starts with $.
  (\{)?          # May be enclosed by { } pair.
  (?P<name>\w+)  # Save the symbol in named group.
  (?(1)\})       # Expect } if and only if { was present.
''', re.VERBOSE | re.ASCII)

def generate_script(output_filename: Path, input_filenames: List[Path]):
  errors: List[Any] = []

  # Create new python script and write the initial setup code.
  output = StringIO()  # File-like in-memory buffer.
  output.write("# DO NOT EDIT: This file was generated by gen-mterp.py.\n")
  output.write(SCRIPT_SETUP_CODE.read_text())
  output.write("def opcodes():\n")
  for i, opcode in enumerate(getOpcodeList()):
    output.write(f'  write_opcode({i}, "{opcode}", {opcode})\n')

  # Read all template files and translate them into python code.
  for filename in sorted(input_filenames):
    location = f"{filename.parent.name}/{filename.name}"

    # Remove all C++ style comments to simplify further processing.
    input = StringIO(filename.read_text())
    for comment in re.finditer(r"//[^\n]*|/\*.*?\*/", input.getvalue(), re.DOTALL):
      input.seek(comment.start())
      input.write("".join(("\n" if c == "\n" else " "for c in comment.group()))
    lines = list(enumerate(input.getvalue().split("\n"), 1))

    # Remove line-continations (merge any slash-ending line with the next line).
    for i in reversed(range(len(lines)-1)):
      if lines[i][1].endswith("\\"):
        lines[i] = (lines[i][0], lines[i][1][:-1] + lines[i+1][1].lstrip('% '))
        lines[i+1] = (lines[i+1][0], "")
    lines = list((n, c) for n, c in lines if c.strip())

    def print_error(i: int, msg: str):
      nonlocal location, lines
      linenum, _ = lines[i]
      errors.append((location, linenum, msg))
      print(f"ERROR[{location}:{linenum}]: {msg}", file=sys.stderr)
      for j in range(max(0, i-2), min(i+2, len(lines))):
        n, c = lines[j]
        print(f"{">>" if j == i else "  "}{n:6}: {c}", file=sys.stderr)
      print("", file=sys.stderr)

    indents: List[str] = [""]
    indent_stmt: Optional[re.Match[str]] = None
    last_auto_indent: Optional[str] = None
    for i, (linenum, line) in enumerate(lines):
      # Extract indentation and code line parts.
      m = line_re.fullmatch(line)
      assert m, f"Can't parse '{line}'"
      indent, code = m.group("indent"), m.group("code")
      if not code:
        continue

      # Convert non-python blocks into pythonic syntax.
      if not line.startswith("%"):
        code = code.replace("\\""\\\\").replace("'""\\'")
        code = variable_re.sub(r"' + to_string(\g<name>) + '", code)
        code = code.replace("$$""$")
        code = f"write_line('{code}')"

      # Normalize the indentation to 2-spaces in the output.
      if any(m.fullmatch(line) for m in automatic_indent_re):
        output_indent = "  " * (len(indents) - 1 + (1 if indent_stmt else 0))
        last_auto_indent = output_indent
      else:
        if len(indent) > len(indents[-1]):
          if not indent_stmt:
            print_error(i, "Unexpected increased indentation")
          indents.append(indent)
        elif indent_stmt:
          print_error(i, f"Expected increased indentation after {indent_stmt.group('name')}")
        indent_stmt = None
        while len(indent) < len(indents[-1]):
          if len(indents) >= 2 and len(indent) > len(indents[-2]):
            print_error(i, "Decreased indentation does not match any outer indentation")
          indents.pop()
        output_indent = "  " * (len(indents) - 1)
        if last_auto_indent is not None and last_auto_indent != output_indent:
          print_error(i, "Indents before and after label/pragma must match (add '% pass')")
        last_auto_indent = None
      if m := next((m for m in [e.fullmatch(line) for e in indent_re] if m), None):
        if not line.startswith("%"):
          code = f"if {code} or True:"  # Assembly-based scoped block.
        indent_stmt = m

      output.write(f"{(output_indent + code):100} # {location}:{linenum}\n")

  if errors:
    sys.exit(1)

  output.write(f"generate('{output_filename}')\n")
  return output.getvalue()

if len(sys.argv) <= 3:
  print("Usage: output_file input_file(s)")
  sys.exit(1)

# Generate the script and execute it.
output_filename = Path(sys.argv[1])
input_filenames = list(map(Path, sys.argv[2:]))
script = generate_script(output_filename, input_filenames)
script_filename = output_filename.with_suffix(".S.py")
script_filename.write_text(script)  # Write to disk for debugging.
exec(compile(script, script_filename, mode='exec'))

Messung V0.5 in Prozent
C=89 H=93 G=90

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.