[PATCH 4/4] scripts/cvt_style.pl: Tool to reformat sources in various ways

From: Joe Perches
Date: Sat Oct 05 2019 - 12:47:11 EST


Trivial tool to reformat source code in various ways.

This is an old tool that was recently updated to convert /* fallthrough */
style comments to the new pseudo-keyword fallthrough;

Typical command line use is:
$ perl scripts/cvt_style --convert=fallthrough <file list>

Available conversions:
all
printk_to_pr_level
printk_KERN_DEBUG_to_pr_debug
dev_printk_to_dev_level
dev_printk_KERN_DEBUG_to_dev_dbg
sdev_printk_to_sdev_level
sdev_printk_KERN_DEBUG_to_sdev_dbg
coalesce_formats
cuddle_open_brace
cuddle_else
deparenthesize_returns
space_after_KERN_level
space_after_if_while_for_switch
space_after_for_semicolons
space_after_comma
space_before_pointer
space_around_trigraph
leading_spaces_to_tabs
coalesce_semicolons
remove_trailing_whitespace
remove_whitespace_before_quoted_newline
remove_whitespace_before_trailing_semicolon
remove_whitespace_before_bracket
remove_parenthesis_whitespace
remove_single_statement_braces
remove_whitespace_after_cast
hoist_assigns_from_if
convert_c99_comments
remove_private_data_casts
remove_static_initializations_to_0
remove_true_false_comparisons
remove_NULL_comparisons
remove_trailing_if_semicolons
network_comments
remove_switchforwhileif_semicolons
detab_else_return
remove_while_while
fallthrough
Additional conversions which may not work well:
(enable individually or with --convert=all --broken)
move_labels_to_column_1
space_around_logical_tests
space_around_assign
space_around_arithmetic
CamelCase_to_camel_case

Use --convert=(comma separated list)
ie: --convert=printk_to_pr_level,coalesce_formats

Output file:
--overwrite => write the changes to the source file
--suffix => suffix to append to new file (default: .style)

Signed-off-by: Joe Perches <joe@xxxxxxxxxxx>
---
scripts/cvt_style.pl | 808 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 808 insertions(+)
create mode 100755 scripts/cvt_style.pl

diff --git a/scripts/cvt_style.pl b/scripts/cvt_style.pl
new file mode 100755
index 000000000000..fcbda0b1c67a
--- /dev/null
+++ b/scripts/cvt_style.pl
@@ -0,0 +1,808 @@
+#!/usr/bin/perl -w
+
+# Change some style elements of a source file
+# An imperfect source code formatter.
+# Might make trivial patches a bit easier.
+#
+# usage: perl scripts/cvt_kernel_style.pl <files>
+#
+# Licensed under the terms of the GNU GPL License version 2
+
+use strict;
+use Getopt::Long qw(:config no_auto_abbrev);
+
+my $P = $0;
+my $V = '0.4';
+
+my $source_indent = 8;
+my $quiet = 0;
+my $stats = 1;
+my $overwrite = 0;
+my $modified = 0;
+my $suffix = ".style";
+my $convert_options = "";
+my $broken = 0;
+
+my @std_options = (
+ "all",
+ "printk_to_pr_level",
+ "printk_KERN_DEBUG_to_pr_debug",
+ "dev_printk_to_dev_level",
+ "dev_printk_KERN_DEBUG_to_dev_dbg",
+ "sdev_printk_to_sdev_level",
+ "sdev_printk_KERN_DEBUG_to_sdev_dbg",
+ "coalesce_formats",
+ "cuddle_open_brace",
+ "cuddle_else",
+ "deparenthesize_returns",
+ "space_after_KERN_level",
+ "space_after_if_while_for_switch",
+ "space_after_for_semicolons",
+ "space_after_comma",
+ "space_before_pointer",
+ "space_around_trigraph",
+ "leading_spaces_to_tabs",
+ "coalesce_semicolons",
+ "remove_trailing_whitespace",
+ "remove_whitespace_before_quoted_newline",
+ "remove_whitespace_before_trailing_semicolon",
+ "remove_whitespace_before_bracket",
+ "remove_parenthesis_whitespace",
+ "remove_single_statement_braces",
+ "remove_whitespace_after_cast",
+ "hoist_assigns_from_if",
+ "convert_c99_comments",
+ "remove_private_data_casts",
+ "remove_static_initializations_to_0",
+ "remove_true_false_comparisons",
+ "remove_NULL_comparisons",
+ "remove_trailing_if_semicolons",
+ "network_comments",
+ "remove_switchforwhileif_semicolons",
+ "detab_else_return",
+ "remove_while_while",
+ "fallthrough",
+);
+
+my @other_options = (
+ "move_labels_to_column_1",
+ "space_around_logical_tests",
+ "space_around_assign",
+ "space_around_arithmetic",
+ "CamelCase_to_camel_case"
+);
+
+my $version = 0;
+my $help = 0;
+
+my $logFunctions = qr{(?x:
+ printk|
+ ([a-z0-9_]+)_(debug|dbg|vdbg|devel|info|warn|warning|err|notice|alert|crit|emerg|cont)|
+ WARN|
+ panic
+)};
+
+my $match_balanced_parentheses = qr/(\((?:[^\(\)]++|(?-1))*\))/;
+my $match_balanced_braces = qr/(\{(?:[^\{\}]++|(?-1))*\})/;
+my $do_cvt;
+
+my %hash;
+
+sub set_all_options {
+ my ($enabled) = @_;
+
+ foreach my $opt (@std_options) {
+ $hash{$opt} = $enabled;
+ }
+
+ if ($broken > 0 || $enabled == -1) {
+ foreach my $opt (@other_options) {
+ $hash{$opt} = $enabled;
+ }
+ }
+
+}
+
+if (!GetOptions(
+ 'source-indent=i' => \$source_indent,
+ 'convert=s' => \$convert_options,
+ 'broken!' => \$broken,
+ 'stats!' => \$stats,
+ 'o|overwrite!' => \$overwrite,
+ 'q|quiet!' => \$quiet,
+ 'v|version' => \$version,
+ 'h|help|usage' => \$help,
+ )) {
+ die "$P: invalid argument - use --help if necessary\n";
+}
+
+if ($help) {
+ usage();
+ exit 0;
+}
+
+if ($version) {
+ print "$P: v$V\n";
+ exit 0;
+}
+
+my $max_spaces_before_tab = $source_indent - 1;
+my $spaces_to_tab = sprintf("%*s", $source_indent, "");
+
+set_all_options(-1);
+
+my @actual_options = split(',', $convert_options);
+foreach my $opt (@actual_options) {
+ if ($opt eq "all") {
+ set_all_options(0);
+ }
+ if (exists($hash{$opt})) {
+ $hash{$opt} = 0;
+ } else {
+ print "Invalid --convert option: '$opt', ignored\n";
+ }
+}
+
+sub usage {
+ print <<EOT;
+usage: $P [options] <files>
+version: $V
+
+EOT
+ print "Available conversions:\n";
+ foreach my $convert (@std_options) {
+ print "\t$convert\n";
+ }
+ print "Additional conversions which may not work well:\n";
+ print "\t(enable individually or with --convert=all --broken)\n";
+ foreach my $convert (@other_options) {
+ print "\t$convert\n";
+ }
+ print "\n";
+ print "Use --convert=(comma separated list)\n";
+ print " ie: --convert=printk_to_pr_level,coalesce_formats\n";
+ print <<EOT;
+
+Input source file descriptions:
+ --source-indent => How many spaces are used for an indent (default: 8)
+
+Output file:
+ --overwrite => write the changes to the source file
+ --suffix => suffix to append to new file (default: .style)
+
+Other options:
+ --quiet => don't show conversion warning messages (default: disabled)
+ --stats => show conversions done (default: enabled)
+ --version => show version
+ --help => show this help information
+EOT
+}
+
+sub check_label {
+ my ($leading, $label) = @_;
+
+ if ($label == "default") {
+ return "$leading$label:";
+ }
+ return "$label:";
+}
+
+sub check_for {
+ my ($leading, $test1, $test2, $test3) = @_;
+
+ $test1 =~ s/^\s+|\s+$//g;
+ $test2 =~ s/^\s+|\s+$//g;
+ $test3 =~ s/^\s+|\s+$//g;
+
+ return "${leading}for ($test1; $test2; $test3)";
+}
+
+sub tabify {
+ my ($leading) = @_;
+
+#convert leading spaces to tabs
+ 1 while $leading =~ s@^([\t]*)$spaces_to_tab@$1\t@g;
+#Remove spaces before a tab
+ 1 while $leading =~ s@^([\t]*)([ ]{1,$max_spaces_before_tab})\t@$1\t@g;
+
+ return "$leading";
+}
+
+sub expand_tabs {
+ my ($str) = @_;
+
+ my $res = '';
+ my $n = 0;
+ for my $c (split(//, $str)) {
+ if ($c eq "\t") {
+ $res .= ' ';
+ $n++;
+ for (; ($n % 8) != 0; $n++) {
+ $res .= ' ';
+ }
+ next;
+ }
+ $res .= $c;
+ $n++;
+ }
+
+ return $res;
+}
+
+sub default_substitute {
+ my ($argument) = @_;
+
+ return "$argument";
+}
+
+sub subst_line_mode_fn {
+ my ($lines, $match, $fn, $args) = @_;
+
+ my $function = \&$fn;
+ my @lines = split("\n", $lines);
+ my $count = 0;
+
+ foreach my $line (@lines) {
+ my $oldline = $line;
+ $line =~ s@$match@&$function(eval $args)@ge;
+ $count++ if ($oldline ne $line);
+ }
+
+ return ($count, join("\n", @lines) . "\n");
+}
+
+sub subst_line_mode {
+ my ($lines, $match, $substitute) = @_;
+
+ return subst_line_mode_fn($lines, $match, "default_substitute", $substitute);
+}
+
+sub convert {
+ my ($check) = @_;
+
+ return 1 if ($hash{$check} >= 0);
+
+ return 0;
+}
+
+sub strip_leading_paren {
+ my ($string) = @_;
+ $string =~ s@^\(\s*@@g;
+ return $string;
+}
+
+sub strip_outer_paren {
+ my ($string) = @_;
+ $string =~ s@^\(\s*@@g;
+ $string =~ s@\s*\)$@@g;
+ return $string;
+}
+
+sub trim_trail {
+ my ($string) = @_;
+ $string =~ s@\s*$@@g;
+ return $string;
+}
+
+
+foreach my $file (@ARGV) {
+ my $f;
+ my $text;
+ my $oldtext;
+
+# read the file
+
+ next if ((-d $file));
+
+ open($f, '<', $file)
+ or die "$P: Can't open $file for read\n";
+ $oldtext = do { local($/) ; <$f> };
+ close($f);
+
+ next if ($oldtext eq "");
+
+ $text = $oldtext;
+
+# Convert printk(KERN_<level> to pr_<level>(
+ $do_cvt = "printk_to_pr_level";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s@\bprintk\s*\(\s*KERN_(INFO|WARNING|ERR|ALERT|CRIT|EMERG|NOTICE|CONT)\s*@pr_\L$1\(@g;
+ $text =~ s@\bpr_warning\b@pr_warn@g;
+
+ $hash{$do_cvt} += $text =~ s@\bprintk_ratelimited\s*\(\s*KERN_(INFO|WARNING|ERR|ALERT|CRIT|EMERG|NOTICE|CONT)\s*@pr_\L$1_ratelimited\(@g;
+ $text =~ s@\bpr_warning_ratelimited\b@pr_warn_ratelimited@g;
+
+ $hash{$do_cvt} += $text =~ s@\bprintk_once\s*\(\s*KERN_(INFO|WARNING|ERR|ALERT|CRIT|EMERG|NOTICE|CONT)\s*@pr_\L$1_once\(@g;
+ $text =~ s@\bpr_warning_once\b@pr_warn_once@g;
+ }
+
+# Convert printk(KERN_DEBUG to pr_debug(
+ $do_cvt = "printk_KERN_DEBUG_to_pr_debug";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s@\bprintk\s*\(\s*KERN_(DEBUG)\s*@pr_\L$1\(@g;
+ }
+
+# Convert dev_printk(KERN_<level> to dev_<level>(
+ $do_cvt = "dev_printk_to_dev_level";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s@\bdev_printk\s*\(\s*KERN_(INFO|WARNING|ERR|ALERT|CRIT|EMERG|NOTICE)\s*,\s*@dev_\L$1\(@g;
+ $text =~ s@\bdev_warning\b@dev_warn@g;
+
+ $hash{$do_cvt} += $text =~ s@\bdev_printk_ratelimited\s*\(\s*KERN_(INFO|WARNING|ERR|ALERT|CRIT|EMERG|NOTICE|CONT)\s*,\s*@dev_\L$1_ratelimited\(@g;
+ $text =~ s@\bdev_warning_ratelimited\b@dev_warn_ratelimited@g;
+
+ $hash{$do_cvt} += $text =~ s@\bdev_printk_once\s*\(\s*KERN_(INFO|WARNING|ERR|ALERT|CRIT|EMERG|NOTICE|CONT)\s*,\s*@dev_\L$1_once\(@g;
+ $text =~ s@\bdev_warning_once\b@dev_warn_once@g;
+ }
+
+# Convert dev_printk(KERN_DEBUG to dev_dbg(
+ $do_cvt = "dev_printk_KERN_DEBUG_to_dev_dbg";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s@\bdev_printk\s*\(\s*KERN_(DEBUG)\s*,\s*@dev_dbg\(@g;
+ }
+
+# Convert sdev_printk(KERN_<level> to sdev_<level>(
+ $do_cvt = "sdev_printk_to_sdev_level";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s@\bsdev_printk\s*\(\s*KERN_(INFO|WARNING|ERR|ALERT|CRIT|EMERG|NOTICE)\s*,\s*@sdev_\L$1\(@g;
+ $text =~ s@\bsdev_warning\b@sdev_warn@g;
+
+ $hash{$do_cvt} += $text =~ s@\bsdev_printk_ratelimited\s*\(\s*KERN_(INFO|WARNING|ERR|ALERT|CRIT|EMERG|NOTICE|CONT)\s*,\s*@sdev_\L$1_ratelimited\(@g;
+ $text =~ s@\bsdev_warning_ratelimited\b@sdev_warn_ratelimited@g;
+
+ $hash{$do_cvt} += $text =~ s@\bsdev_printk_once\s*\(\s*KERN_(INFO|WARNING|ERR|ALERT|CRIT|EMERG|NOTICE|CONT)\s*,\s*@sdev_\L$1_once\(@g;
+ $text =~ s@\bsdev_warning_once\b@sdev_warn_once@g;
+ }
+
+# Convert sdev_printk(KERN_DEBUG to sdev_dbg(
+ $do_cvt = "sdev_printk_KERN_DEBUG_to_sdev_dbg";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s@\bsdev_printk\s*\(\s*KERN_(DEBUG)\s*,\s*@sdev_dbg\(@g;
+ }
+
+# Coalesce long formats
+ $do_cvt = "coalesce_formats";
+ if (convert($do_cvt)) {
+ my $count = 0;
+ do {
+ $count = $text =~ s@\b(${logFunctions}\s*\([^;]+)(?!\\n)\"\s*\n\s*\"@$1@g;
+ $hash{$do_cvt} += $count;
+ } while ($count > 0);
+ }
+
+# Add space between KERN_<LEVEL> and open quote
+ $do_cvt = "space_after_KERN_level";
+ if (convert($do_cvt)) {
+ my @matches = $text =~ m@\b(KERN_(DEBUG|INFO|WARNING|ERR|ALERT|CRIT|EMERG|NOTICE|CONT)) \"@g;
+ $hash{$do_cvt} -= @matches;
+ $hash{$do_cvt} += $text =~ s@\b(KERN_(DEBUG|INFO|WARNING|ERR|ALERT|CRIT|EMERG|NOTICE|CONT))[ \t]*\"@$1 \"@g;
+ }
+
+# Remove unnecessary parentheses around return
+ $do_cvt = "deparenthesize_returns";
+ if (convert($do_cvt)) {
+ my $count = 0;
+ do {
+ $count = $text =~ s@\breturn\s*${match_balanced_parentheses}\s*;@"return " . scalar(strip_outer_paren($1)) . ";"@egx;
+ $hash{$do_cvt} += $count;
+ } while ($count > 0);
+ }
+
+# This doesn't work very well, too many comments modified
+# Put labels (but not "default:") on column 1
+ $do_cvt = "move_labels_to_column_1";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s@^([ \t]+)([A-Za-z0-9_]+)\s*:[ \t]*:[ \t]*$@check_label($1, $2)@ge;
+ }
+
+# Add space after (if, while, for, switch) and open parenthesis
+ $do_cvt = "space_after_if_while_for_switch";
+ if (convert($do_cvt)) {
+ my @matches = $text =~ m@\b(if|while|for|switch) \(@g;
+ $hash{$do_cvt} -= @matches;
+ $hash{$do_cvt} += $text =~ s@\b(if|while|for|switch)[ \t]*\(@$1 \(@g;
+ }
+
+# Add space after comma
+ $do_cvt = "space_after_comma";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s@,(?=[\w\(])@, @g;
+ }
+
+# Add spaces around logical tests
+ $do_cvt = "space_around_logical_tests";
+ if (convert($do_cvt)) {
+ my $count = 0;
+ do {
+ $count = $text =~ s@([\)\w]+)(==|!=|>|>=|<|<=|&&|\|\|)([\(\w\*\-])@$1 $2 $3@g;
+ $hash{$do_cvt} += $count;
+ } while ($count > 0);
+ }
+
+# Add spaces around assign
+ $do_cvt = "space_around_assign";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s@([\)\w]+)(=|\+=|\-=|\*=|/=|>>=|<<=)([\(\w\*\-])@$1 $2 $3@g;
+ }
+
+# Add spaces around arithmetic
+ $do_cvt = "space_around_arithmetic";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s@([\)\w]+)(\+|\-)([\(\w\*])@$1 $2 $3@g;
+ }
+
+# Add spaces around trigraph
+ $do_cvt = "space_around_trigraph";
+ if (convert($do_cvt)) {
+ my @matches = $text =~ m@([\)\w\"]+) \? ([\(\)\[\]\w\*\" \t\.\>\-]*[^ \t]) \: ([\w\(\"\-])@g;
+ $hash{$do_cvt} -= @matches;
+ $hash{$do_cvt} += $text =~ s@([\)\w\"]+)[ \t]*\?[ \t]*([\(\)\[\]\w\*\" \t\.\>\-]*[^ \t])[ \t]*\:[ \t]*([\w\(\"\-])@$1 ? $2 : $3@g;
+ }
+
+# Use a space before a pointer,
+ $do_cvt = "space_before_pointer";
+ if (convert($do_cvt)) {
+ my @matches = $text =~ m@\bstruct \w+ \*@g;
+ $hash{$do_cvt} -= @matches;
+ $hash{$do_cvt} += $text =~ s@\bstruct\b\s+(\w+)([\t]+)\*[ \t]*@struct $1$2\*@g;
+ $hash{$do_cvt} += $text =~ s@\bstruct\b\s+(\w+) *\*[ \t]*@struct $1 \*@g;
+ $hash{$do_cvt} += $text =~ s@\bstruct\b\s+(\w+)([ \t]+)\*__@struct $1$2\* __@g;
+ }
+
+# Convert "for (foo;bar;baz)" to "for (foo; bar; baz)"
+ $do_cvt = "space_after_for_semicolons";
+ if (convert($do_cvt)) {
+ my $count;
+ ($count, $text) = subst_line_mode_fn($text, '^([ \t]*)for\s*\([ \t]*([^;]+);[ \t]*([^;]+);[ \t]*([^\)]+)\)', 'check_for', '$1, $2, $3, $4');
+ $hash{$do_cvt} += $count;
+ }
+
+# cuddle open brace
+ $do_cvt = "cuddle_open_brace";
+ if (convert($do_cvt)) {
+ my @matches = $text =~ m@(\)|\belse\b) \{\n@g;
+ $hash{$do_cvt} -= @matches;
+ $hash{$do_cvt} += $text =~ s@(\)|\belse\b|\bcase\s+\w+\s*:|\b(?:struct|union)[ \t]*(?:\w+|))[ \t]*[ \t]*\n[ \t]+\{[ \t]*\n@$1 \{\n@g;
+ }
+
+# cuddle else
+ $do_cvt = "cuddle_else";
+ if (convert($do_cvt)) {
+ my @matches = $text =~ m@\} else\b@g;
+ $hash{$do_cvt} -= @matches;
+ $hash{$do_cvt} += $text =~ s@\}[ \t]*\n[ \t]+else\b@\} else@g;
+ }
+
+# Remove multiple semicolons at end-of-line
+ $do_cvt = "coalesce_semicolons";
+ if (convert($do_cvt)) {
+ my $count = 0;
+ do {
+ $count = $text =~ s@;[ \t]*;[ \t]*\n@;\n@g;
+ $hash{$do_cvt} += $count;
+ } while ($count > 0);
+ }
+
+# Remove spaces before open bracket
+ $do_cvt = "remove_whitespace_before_bracket";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s@[ \t]+\[@\[@g;
+ }
+
+# Remove spaces after open parenthesis and before close parenthesis
+ $do_cvt = "remove_parenthesis_whitespace";
+ if (convert($do_cvt)) {
+ $text =~ s@[ \t]*\)@\)@g;
+ $text =~ s@\([ \t]*@\(@g;
+ }
+
+# Convert leading spaces to tabs
+ $do_cvt = "leading_spaces_to_tabs";
+ if (convert($do_cvt)) {
+ my $count;
+ ($count, $text) = subst_line_mode_fn($text, '(^[ \t]+)', 'tabify', '$1');
+ $hash{$do_cvt} += $count;
+ }
+
+# Remove trailing whitespace
+ $do_cvt = "remove_trailing_whitespace";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s@[ \t]+\n@\n@g;
+ $hash{$do_cvt} += $text =~ s@\n+$@\n@g;
+ }
+
+# Remove whitespace before quoted newlines
+ $do_cvt = "remove_whitespace_before_quoted_newline";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s@(\"[^\"\n]*[^ \t])[ \t]+\\n@$1\\n@g;
+ }
+
+# Remove whitespace before trailing semicolon
+ $do_cvt = "remove_whitespace_before_trailing_semicolon";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s@(\n[^\n]+)\s+;[ \t]*\n$@$1;\n@g;
+ }
+
+# Remove whitespace after cast
+ $do_cvt = "remove_whitespace_after_cast";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s@[ \t]*\*[ \t]*\)[ \t]+@ \*\)@g;
+ }
+
+# Convert c99 comments to /* */ (don't convert (http|ftp)://)
+ $do_cvt = "convert_c99_comments";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s@(?<!:)\/\/[ \t]*(.*)[ \t]*\n+@\/* $1 *\/\n@g;
+ }
+
+# Remove braces from single statements (not multiple-line single statements)
+ $do_cvt = "remove_single_statement_braces";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s@[ \t]*\{[ \t]*\n([^;\{\n]+;)[ \t]*\n[ \t]+\}[ \t]*\n@\n$1\n@g;
+ }
+
+# Hoist assigns from if
+ $do_cvt = "hoist_assigns_from_if";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s@\n([ \t]*)if\s*\(\s*([\!]{0,1})\s*\(\s*([\*\w\-\>\.\[\]]+)\s*=\s*(?=[^=])\s*([\w\-\>\.\* \t\[\]]*\s*${match_balanced_parentheses}*\s*(\?\:\&|\||\>\>|\<\<|\-|\+|\*|\/ \t)*\s*[\w\-\>\.\* \t\[\]]*\s*${match_balanced_parentheses}*)\s*\)@\n$1$3 = $4;\n$1if \($2$3@gx;
+ }
+
+# Remove casts of private_data
+ $do_cvt = "remove_private_data_casts";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s/=\s*\(\s*\w+\s*\w+\s*\*\s*\)\s*(\w+)->\s*private_data\b/= $1->private_data/g;
+ }
+
+# Remove static initializations to 0 or NULL
+
+ $do_cvt = "remove_static_initializations_to_0";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s/\b([ \t]*)static\s*([\w\t \*]+)\s*=\s*(0|NULL)\s*;/"$1static " . scalar(trim_trail($2)) . ";"/egx;
+ }
+
+# Convert "CamelCase" to "camel_case"
+ $do_cvt = "CamelCase_to_camel_case";
+ if (convert($do_cvt)) {
+ my $count = 0;
+ do {
+ $count = $text =~ s/\b([A-Za-z])([a-z_]+)([A-Z])([a-zA-Z]+)\b/\L$1\E$2_\L$3\E$4/g;
+ $hash{$do_cvt} += $count;
+ } while ($count > 0);
+ }
+
+# Remove comparisons to true or false
+ $do_cvt = "remove_true_false_comparisons";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s/(\([^\=\;\{\}\(]+)==\s*true\s*\)/"(" . scalar(strip_leading_paren(trim_trail($1))) . ")"/egx;
+ $hash{$do_cvt} += $text =~ s/(\([^\!\;\{\}\(]+)!=\s*true\s*\)/"(!" . scalar(strip_leading_paren(trim_trail($1))) . ")"/egx;
+ $hash{$do_cvt} += $text =~ s/(\([^\=\;\{\}\(]+)==\s*false\s*\)/"(!" . scalar(strip_leading_paren(trim_trail($1))) . ")"/egx;
+ $hash{$do_cvt} += $text =~ s/(\([^\!\;\{\}\(]+)!=\s*false\s*\)/"(" . scalar(strip_leading_paren(trim_trail($1))) . ")"/egx;
+ }
+
+# Remove comparisons to NULL
+ $do_cvt = "remove_NULL_comparisons";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s/(\([^\=\;\{\}\(]+)==\s*NULL\s*\)/"(!" . scalar(strip_leading_paren(trim_trail($1))) . ")"/egx;
+ $hash{$do_cvt} += $text =~ s/(\([^\!\;\{\}\(]+)!=\s*NULL\s*\)/"(" . scalar(strip_leading_paren(trim_trail($1))) . ")"/egx;
+ }
+
+# Remove trailing if semicolons
+ $do_cvt = "remove_trailing_if_semicolons";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s/\bif(\s*)($match_balanced_parentheses)\s*;(?!\s*(else|\/\*))/if$1$2/g;
+ }
+
+# Convert normal comments to network comments
+ $do_cvt = "network_comments";
+ if (convert($do_cvt)) {
+ $hash{$do_cvt} += $text =~ s@/\*[ \t]*\n[ \t]*\*@/*@g;
+ $hash{$do_cvt} += $text =~ s@/\*([ \t]*)([^\n]+)\n[ \t]*\*/@/\*$1$2 \*/@g;
+ }
+
+# Remove unnecessary semicolons after switch () {};
+ $do_cvt = "remove_switchforwhileif_semicolons";
+ if (convert($do_cvt)) {
+ my $count = 0;
+ do {
+ $count = 0;
+ $count += $text =~ s@\b((?:switch|for|while|if)\s*${match_balanced_parentheses}\s*)${match_balanced_braces}\s*;@"$1$3"@egx;
+ $hash{$do_cvt} += $count;
+ } while ($count > 0);
+ }
+
+# detab_else_return
+ $do_cvt = "detab_else_return";
+ if (convert($do_cvt)) {
+ my $count = 0;
+ do {
+ $count = 0;
+ $count += $text =~ s@(?!else\s+)\b(if\s*${match_balanced_parentheses}\s*)${match_balanced_braces}\s*else\s*\{?\s*return\s+([^;]+;)\s*\}?@"$1$3"@egx;
+ $hash{$do_cvt} += $count;
+ } while ($count > 0);
+ }
+
+# Remove while while loops
+ $do_cvt = "remove_while_while";
+ if (convert($do_cvt)) {
+ my $count = 0;
+ do {
+ $count = 0;
+ $count += $text =~ s@(while\s*(${match_balanced_parentheses})\s*${match_balanced_braces})\s*while\s*\2\s*;@$1@egx;
+ $hash{$do_cvt} += $count;
+ } while ($count > 0);
+ }
+
+# Remove fallthrough comments and convert to fallthrough;
+ $do_cvt = "fallthrough";
+ if (convert($do_cvt)) {
+
+ # for style:
+
+ # /* <fallthrough comment> */
+ # case FOO:
+
+ # while (comment has fallthrough and next non-blank, non-continuation line is (case or default:)) {
+ # remove newline, whitespace before, fallthrough comment and whitespace after
+ # insert newline, adjusted spacing and fallthrough; newline
+ # }
+
+ my $count = 0;
+ my @fallthroughs = (
+ 'fallthrough',
+ '@fallthrough@',
+ 'lint -fallthrough[ \t]*',
+ '[ \t.!]*(?:ELSE,? |INTENTIONAL(?:LY)? )?',
+ 'intentional(?:ly)?[ \t]*fall(?:(?:s | |-)[Tt]|t)hr(?:ough|u|ew)',
+ '(?:else,?\s*)?FALL(?:S | |-)?THR(?:OUGH|U|EW)[ \t.!]*(?:-[^\n\r]*)?',
+ '[ \t.!]*(?:Else,? |Intentional(?:ly)? )?',
+ 'Fall(?:(?:s | |-)[Tt]|t)hr(?:ough|u|ew)[ \t.!]*(?:-[^\n\r]*)?',
+ '[ \t.!]*(?:[Ee]lse,? |[Ii]ntentional(?:ly)? )?',
+ 'fall(?:s | |-)?thr(?:ough|u|ew)[ \t.!]*(?:-[^\n\r]*)?',
+ );
+ do {
+ $count = 0;
+ pos($text) = 0;
+ foreach my $ft (@fallthroughs) {
+ my $regex = '(((?:[ \t]*\n)*[ \t]*)(/\*\s*(?!\*/)?\b' . "$ft" . '\s*(?!\*/)?\*/(?:[ \t]*\n)*)([ \t]*))(?:case\s+|default\s*:)';
+
+ while ($text =~ m{${regex}}i) {
+ my $all_but_case = $1;
+ my $space_before = $2;
+ my $fallthrough = $3;
+ my $space_after = $4;
+ my $pos_before = $-[1];
+ my $pos_after = $+[3];
+
+ # try to maintain any additional comment on the same line
+ my $comment = "";
+ if ($regex =~ /\\r/) {
+ $comment = $fallthrough;
+ $comment =~ s@^/\*\s*@@;
+ $comment =~ s@\s*\*/\s*$@@;
+ $comment =~ s@^\s*(?:intentional(?:ly)?\s+|else,?\s*)?fall[s\-]*\s*thr(?:ough|u|ew)[\s\.\-]*@@i;
+ $comment =~ s@\s+$@@;
+ $comment =~ s@\.*$@@;
+ $comment = "\t/* $comment */" if ($comment ne "");
+ }
+ substr($text, $pos_before, $pos_after - $pos_before, "");
+ substr($text, $pos_before, 0, "\n${space_after}\tfallthrough;${comment}\n");
+ pos($text) = $pos_before;
+ $count++;
+ }
+ }
+ $hash{$do_cvt} += $count;
+ } while ($count > 0);
+
+ # Reset the fallthroughs types to a single regex
+
+ @fallthroughs = (
+ 'fall(?:(?:s | |-)[Tt]|t)hr(?:ough|u|ew)'
+ );
+
+ # Convert the // <fallthrough> style comments followed by case/default:
+
+ do {
+ $count = 0;
+ pos($text) = 0;
+ foreach my $ft (@fallthroughs) {
+ my $regex = '(((?:[ \t]*\n)*[ \t]*)(//[ \t]*(?!\n)?\b' . "$ft" . '[ \t]*(?!\n)?\n(?:[ \t]*\n)*)([ \t]*))(?:case\s+|default\s*:)';
+ while ($text =~ m{${regex}}i) {
+ my $all_but_case = $1;
+ my $space_before = $2;
+ my $fallthrough = $3;
+ my $space_after = $4;
+ my $pos_before = $-[1];
+ my $pos_after = $+[3];
+
+ substr($text, $pos_before, $pos_after - $pos_before, "");
+ substr($text, $pos_before, 0, "\n${space_after}\tfallthrough;\n");
+ pos($text) = $pos_before;
+ $count++;
+ }
+ }
+ $hash{$do_cvt} += $count;
+ } while ($count > 0);
+
+ # Convert /* fallthrough */ comment macro lines with trailing \
+
+ do {
+ $count = 0;
+ pos($text) = 0;
+ foreach my $ft (@fallthroughs) {
+ my $regex = '((?:[ \t]*\\\\\n)*([ \t]*)(/\*[ \t]*\b' . "$ft" . '[ \t]*\*/)([ \t]*))\\\\\n*([ \t]*(?:case\s+|default\s*:))';
+
+ while ($text =~ m{${regex}}i) {
+ my $all_but_case = $1;
+ my $space_before = $2;
+ my $fallthrough = $3;
+ my $space_after = $4;
+ my $pos_before = $-[2];
+ my $pos_after = $+[4];
+
+ my $oldline = "${space_before}${fallthrough}${space_after}";
+ my $len = length(expand_tabs($oldline));
+
+ my $newline = "${space_before}fallthrough;${space_after}";
+ $newline .= "\t" while (length(expand_tabs($newline)) < $len);
+
+ substr($text, $pos_before, $pos_after - $pos_before, "");
+ substr($text, $pos_before, 0, "$newline");
+ pos($text) = $pos_before;
+ $count++;
+ }
+ }
+ $hash{$do_cvt} += $count;
+ } while ($count > 0);
+
+ }
+
+# write the file if something was changed
+
+ if ($text ne $oldtext) {
+ my $newfile = $file;
+
+ $modified = 1;
+
+ if (!$overwrite) {
+ $newfile = "$newfile$suffix";
+ }
+ open($f, '>', $newfile)
+ or die "$P: Can't open $newfile for write\n";
+ print $f $text;
+ close($f);
+
+ if (!$quiet || $stats) {
+ if ($overwrite) {
+ print "Converted $file\n";
+ } else {
+ print "Converted $file to $newfile\n";
+ }
+ }
+
+ if ($stats) {
+ while ((my $key, my $value) = each(%hash)) {
+ next if ($value <= 0);
+ print "$value\t$key\n" if $value;
+ $hash{$key} = 0; #Reset for next file
+ }
+ }
+ }
+}
+
+
+if ($modified && !$quiet) {
+ print <<EOT;
+
+Warning: these changes may not be correct.
+
+These changes should be carefully reviewed manually and not combined with
+any functional changes.
+
+Compile, build and test your changes.
+
+You should understand and be responsible for all object changes.
+
+Make sure you read Documentation/SubmittingPatches before sending
+any changes to reviewers, maintainers or mailing lists.
+EOT
+}
--
2.15.0