Commit Message
Hello.
Sometimes, one needs a more complex replacement in source files and
an editor can be a weak tool. That has happened to me in the recent
time and so I made the replacement in Python.
The script provides simple API:
- handle_file_p - return True if you want to touch the file
- modify_line - return modified line (if you want)
Are others also interested or should I put it to my internal tools?
Cheers,
Martin
contrib/ChangeLog:
* replace.py: New file.
---
contrib/replace.py | 92 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 92 insertions(+)
create mode 100755 contrib/replace.py
new file mode 100755
@@ -0,0 +1,92 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2021 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING. If not, write to
+# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+# The script can be used for more complex replacements in the source code.
+#
+
+import argparse
+import os
+import re
+import sys
+
+EXTENSIONS = ('.h', '.c', '.cc', '.C')
+
+
+def handle_file_p(filename):
+ if 'testsuite' in filename:
+ return False
+ if all(not filename.endswith(ext) for ext in EXTENSIONS):
+ return False
+
+ return True
+
+
+def modify_line(line):
+ # Example replacement:
+ # m = re.match(r'.*time_function\(&([^,]*),', line)
+ # if m:
+ # e = m.end(1)
+ # name = m.group(1)
+ # line = line[:e + 1] + f' "{name}",' + line[e + 1:]
+
+ return line
+
+
+parser = argparse.ArgumentParser(description='Make a custom replacements '
+ 'for source files')
+parser.add_argument('directory', help='Root directory')
+parser.add_argument('-v', '--verbose', action='store_true',
+ help='Verbose output')
+args = parser.parse_args()
+
+visited_files = 0
+modified_files = 0
+
+for root, _, files in os.walk(sys.argv[1]):
+ for file in files:
+ full = os.path.join(root, file)
+ if not handle_file_p(full):
+ continue
+
+ visited_files += 1
+
+ modified = False
+ try:
+ modified_lines = []
+ with open(full) as f:
+ lines = f.readlines()
+ for line in lines:
+ modified_line = modify_line(line)
+ if line != modified_line:
+ modified = True
+ modified_lines.append(line)
+ if modified:
+ with open(full, 'w') as w:
+ w.write('\n'.join(modified_lines))
+ modified_files += 1
+ if args.verbose:
+ print(f'File modified: {full}')
+ except UnicodeDecodeError as e:
+ print(f'Skipping file: {full} ({e})')
+
+
+print(f'Visited files: {visited_files}')
+print(f'Modified files: {modified_files}')