From: Breno Rodrigues Alves <breno3011alves@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: Andy Whitcroft <apw@canonical.com>, Joe Perches <joe@perches.com>,
Dwaipayan Ray <dwaipayanray1@gmail.com>,
Lukas Bulwahn <lukas.bulwahn@gmail.com>,
Breno Rodrigues Alves <breno3011alves@gmail.com>
Subject: [RFC PATCH 2/4] scripts: convert checkincludes.pl to Python
Date: Sun, 18 Oct 2026 07:12:25 -0300 [thread overview]
Message-ID: <20261018101227.7680-3-breno3011alves@gmail.com> (raw)
In-Reply-To: <20261018101227.7680-1-breno3011alves@gmail.com>
Faithful re-implementation of checkincludes.pl in Python 3
(stdlib only). Same -r behavior, same duplicate detection,
same error messages.
Tested with a C file containing a duplicate stdio.h include;
output is byte-for-byte identical to the Perl version.
Signed-off-by: Breno Rodrigues Alves <breno3011alves@gmail.com>
---
scripts/checkincludes.py | 101 +++++++++++++++++++++++++++++++++++++++
1 file changed, 101 insertions(+)
create mode 100755 scripts/checkincludes.py
diff --git a/scripts/checkincludes.py b/scripts/checkincludes.py
new file mode 100755
index 000000000..7e85e4bda
--- /dev/null
+++ b/scripts/checkincludes.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+#
+# checkincludes: find/remove files included more than once
+#
+# Copyright abandoned, 2000, Niels Kristian Bech Jensen <nkbj@image.dk>.
+# Copyright 2009 Luis R. Rodriguez <mcgrof@gmail.com>
+#
+# Checks for duplicate #include directives. With -r, removes duplicates
+# in place. Does not account for macros or #ifdef branches; run only when
+# you know the duplicates are real.
+
+import re
+import sys
+
+RE_INCLUDE = re.compile(r'^\s*#\s*include\s*[<"](\S*)[>"]')
+
+
+def usage():
+ print("Usage: checkincludes.py [-r]", file=sys.stderr)
+ print("By default we just warn of duplicates", file=sys.stderr)
+ print("To remove duplicated includes in place use -r", file=sys.stderr)
+ sys.exit(1)
+
+
+def process_file(path, remove):
+ """Return (dup_count, error_msg). error_msg is None on success."""
+ try:
+ with open(path, 'r') as f:
+ lines = f.readlines()
+ except OSError as e:
+ return 0, f"Cannot open {path}: {e}"
+
+ included = {}
+ for line in lines:
+ m = RE_INCLUDE.match(line)
+ if m:
+ included[m.group(1)] = included.get(m.group(1), 0) + 1
+
+ if not remove:
+ dups = 0
+ for filename, n in included.items():
+ if n > 1:
+ print(f"{path}: {filename} is included more than once.")
+ dups += 1
+ return dups, None
+
+ # Removal mode: keep the last occurrence, remove earlier duplicates.
+ # Same semantics as the Perl original (first N-1 occurrences removed).
+ dups = 0
+ out_lines = []
+ for line in lines:
+ m = RE_INCLUDE.match(line)
+ if m and included.get(m.group(1), 0) > 1:
+ included[m.group(1)] -= 1
+ dups += 1
+ else:
+ out_lines.append(line)
+
+ # Match original: always rewrite, even when nothing was removed.
+ try:
+ with open(path, 'w') as f:
+ f.writelines(out_lines)
+ except OSError as e:
+ return 0, f"Cannot write to {path}: {e}"
+
+ if dups > 0:
+ print(f"{path}: removed {dups} duplicate includes")
+ return dups, None
+
+
+def main(argv):
+ remove = False
+ args = list(argv)
+
+ if not args:
+ usage()
+
+ # Original only parses "-r" when there are >= 2 args.
+ if len(args) >= 2 and args[0].startswith('-'):
+ if args[0] == '-r':
+ remove = True
+ args.pop(0)
+ else:
+ usage()
+
+ dup_counter = 0
+ for path in args:
+ n, err = process_file(path, remove)
+ if err:
+ print(err, file=sys.stderr)
+ sys.exit(1)
+ dup_counter += n
+
+ if dup_counter == 0:
+ print("No duplicate includes found.")
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
\ No newline at end of file
--
2.43.0
next prev parent reply other threads:[~2026-10-18 10:12 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-18 10:12 [RFC PATCH 0/4] scripts: convert four small Perl utilities " Breno Rodrigues Alves
2026-10-18 10:12 ` [RFC PATCH 1/4] scripts: convert bootgraph.pl " Breno Rodrigues Alves
2026-10-18 10:12 ` Breno Rodrigues Alves [this message]
2026-10-18 10:12 ` [RFC PATCH 3/4] scripts: convert markup_oops.pl " Breno Rodrigues Alves
2026-10-18 10:12 ` [RFC PATCH 4/4] scripts: convert profile2linkerlist.pl " Breno Rodrigues Alves
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261018101227.7680-3-breno3011alves@gmail.com \
--to=breno3011alves@gmail.com \
--cc=apw@canonical.com \
--cc=dwaipayanray1@gmail.com \
--cc=joe@perches.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lukas.bulwahn@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®