llvm-project/lldb/scripts/convert-lldb-header-to-rpc-header.py
Chelsea Cassanova 92a7f6fbbe
[lldb][rpc] Fix bug in convert script for RPC (#145419)
In the script that's used by RPC to convert LLDB headers to LLDB RPC
headers, there's a bug with how it converts namespace usage. An
overeager regex pattern caused *all* text before any `lldb::` namespace
usage to get replaced with `lldb_rpc::` instead of just the namespace
itself. This commit changes that regex pattern to be less overeager and
modifies one of the shell tests for this script to actually check that
the namespace usage replacement is working correctly.

rdar://154126268
2025-06-23 15:46:12 -07:00

109 lines
4.0 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Usage: convert-lldb-header-to-rpc-header.py <path/to/input-header.h> <path/to/output-header.h>
This scripts takes common LLDB headers (such as lldb-defines.h) and replaces references to LLDB
with those for RPC. This happens for:
- namespace definitions
- namespace usage
- version string macros
- ifdef/ifndef lines
"""
import argparse
import os
import re
INCLUDES_TO_REMOVE_REGEX = re.compile(
r'#include "lldb/lldb-forward.h"|#include "lldb/lldb-versioning.h"'
)
LLDB_GUARD_REGEX = re.compile(r"(?P<guard_type>#.+)LLDB_LLDB_\s*", re.M)
LLDB_API_GUARD_REGEX = re.compile(r"(?P<guard_type>#.+)LLDB_API_\s*", re.M)
LLDB_VERSION_REGEX = re.compile(r"#define LLDB_VERSION", re.M)
LLDB_REVISION_REGEX = re.compile(r"#define LLDB_REVISION", re.M)
LLDB_VERSION_STRING_REGEX = re.compile(r"#define LLDB_VERSION_STRING", re.M)
LLDB_LOCAL_INCLUDE_REGEX = re.compile(r'#include "lldb/lldb-\s*', re.M)
LLDB_NAMESPACE_DEFINITION_REGEX = re.compile(
r"(?P<comment_marker>//\s*){,1}namespace lldb\s{1}", re.M
)
LLDB_NAMESPACE_REGEX = re.compile(r"lldb::\s*", re.M)
def main():
parser = argparse.ArgumentParser()
parser.add_argument("input")
parser.add_argument("output")
args = parser.parse_args()
input_path = str(args.input)
output_path = str(args.output)
with open(input_path, "r") as input_file:
lines = input_file.readlines()
file_buffer = "".join(lines)
with open(output_path, "w") as output_file:
# NOTE: We do not use lldb-forward.h or lldb-versioning.h in RPC, so remove
# all includes that are found for these files.
file_buffer = re.sub(INCLUDES_TO_REMOVE_REGEX, r"", file_buffer)
# For lldb-rpc-defines.h, replace the ifndef LLDB_LLDB_ portion with LLDB_RPC_ as we're not
# using LLDB private definitions in RPC.
lldb_guard_matches = LLDB_GUARD_REGEX.finditer(file_buffer)
for match in lldb_guard_matches:
file_buffer = re.sub(
match.group(),
r"{0}LLDB_RPC_".format(match.group("guard_type")),
file_buffer,
)
# Similarly to lldb-rpc-defines.h, replace the ifndef for LLDB_API in SBDefines.h to LLDB_RPC_API_ for the same reason.
lldb_api_guard_matches = LLDB_API_GUARD_REGEX.finditer(file_buffer)
for match in lldb_api_guard_matches:
file_buffer = re.sub(
match.group(),
r"{0}LLDB_RPC_API_".format(match.group("guard_type")),
file_buffer,
)
# Replace the references for the macros that define the versioning strings in
# lldb-rpc-defines.h.
# NOTE: Here we assume that the versioning info has already been uncommented and
# populated from the original lldb-defines.h.
file_buffer = re.sub(
LLDB_VERSION_REGEX, r"#define LLDB_RPC_VERSION", file_buffer
)
file_buffer = re.sub(
LLDB_REVISION_REGEX, r"#define LLDB_RPC_REVISION", file_buffer
)
file_buffer = re.sub(
LLDB_VERSION_STRING_REGEX, r"#define LLDB_RPC_VERSION_STRING", file_buffer
)
# For local #includes
file_buffer = re.sub(
LLDB_LOCAL_INCLUDE_REGEX, r'#include "lldb-rpc-', file_buffer
)
# Rename the lldb namespace definition to lldb-rpc.
lldb_rpc_namespace_definition_matches = (
LLDB_NAMESPACE_DEFINITION_REGEX.finditer(file_buffer)
)
for match in lldb_rpc_namespace_definition_matches:
comment_marker = (
match.group("comment_marker") if match.group("comment_marker") else ""
)
file_buffer = re.sub(
match.group(),
r"{0}namespace lldb_rpc ".format(comment_marker),
file_buffer,
)
# Rename the lldb namespace definition to lldb-rpc.
file_buffer = re.sub(LLDB_NAMESPACE_REGEX, r"lldb_rpc::", file_buffer)
output_file.write(file_buffer)
if __name__ == "__main__":
main()