| xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 1 | #!/usr/bin/perl -w | 
|  | 2 | # SPDX-License-Identifier: GPL-2.0 | 
|  | 3 |  | 
|  | 4 | use strict; | 
|  | 5 | use Getopt::Long qw(:config no_auto_abbrev); | 
|  | 6 |  | 
|  | 7 | my $input_file = "MAINTAINERS"; | 
|  | 8 | my $output_file = "MAINTAINERS.new"; | 
|  | 9 | my $output_section = "SECTION.new"; | 
|  | 10 | my $help = 0; | 
|  | 11 |  | 
|  | 12 | my $P = $0; | 
|  | 13 |  | 
|  | 14 | if (!GetOptions( | 
|  | 15 | 'input=s' => \$input_file, | 
|  | 16 | 'output=s' => \$output_file, | 
|  | 17 | 'section=s' => \$output_section, | 
|  | 18 | 'h|help|usage' => \$help, | 
|  | 19 | )) { | 
|  | 20 | die "$P: invalid argument - use --help if necessary\n"; | 
|  | 21 | } | 
|  | 22 |  | 
|  | 23 | if ($help != 0) { | 
|  | 24 | usage(); | 
|  | 25 | exit 0; | 
|  | 26 | } | 
|  | 27 |  | 
|  | 28 | sub usage { | 
|  | 29 | print <<EOT; | 
|  | 30 | usage: $P [options] <pattern matching regexes> | 
|  | 31 |  | 
|  | 32 | --input => MAINTAINERS file to read (default: MAINTAINERS) | 
|  | 33 | --output => sorted MAINTAINERS file to write (default: MAINTAINERS.new) | 
|  | 34 | --section => new sorted MAINTAINERS file to write to (default: SECTION.new) | 
|  | 35 |  | 
|  | 36 | If <pattern match regexes> exist, then the sections that match the | 
|  | 37 | regexes are not written to the output file but are written to the | 
|  | 38 | section file. | 
|  | 39 |  | 
|  | 40 | EOT | 
|  | 41 | } | 
|  | 42 |  | 
|  | 43 | # sort comparison functions | 
|  | 44 | sub by_category($$) { | 
|  | 45 | my ($a, $b) = @_; | 
|  | 46 |  | 
|  | 47 | $a = uc $a; | 
|  | 48 | $b = uc $b; | 
|  | 49 |  | 
|  | 50 | # This always sorts last | 
|  | 51 | $a =~ s/THE REST/ZZZZZZ/g; | 
|  | 52 | $b =~ s/THE REST/ZZZZZZ/g; | 
|  | 53 |  | 
|  | 54 | return $a cmp $b; | 
|  | 55 | } | 
|  | 56 |  | 
|  | 57 | sub by_pattern($$) { | 
|  | 58 | my ($a, $b) = @_; | 
|  | 59 | my $preferred_order = 'MRPLSWTQBCFXNK'; | 
|  | 60 |  | 
|  | 61 | my $a1 = uc(substr($a, 0, 1)); | 
|  | 62 | my $b1 = uc(substr($b, 0, 1)); | 
|  | 63 |  | 
|  | 64 | my $a_index = index($preferred_order, $a1); | 
|  | 65 | my $b_index = index($preferred_order, $b1); | 
|  | 66 |  | 
|  | 67 | $a_index = 1000 if ($a_index == -1); | 
|  | 68 | $b_index = 1000 if ($b_index == -1); | 
|  | 69 |  | 
|  | 70 | if (($a1 =~ /^F$/ && $b1 =~ /^F$/) || | 
|  | 71 | ($a1 =~ /^X$/ && $b1 =~ /^X$/)) { | 
|  | 72 | return $a cmp $b; | 
|  | 73 | } | 
|  | 74 |  | 
|  | 75 | if ($a_index < $b_index) { | 
|  | 76 | return -1; | 
|  | 77 | } elsif ($a_index == $b_index) { | 
|  | 78 | return 0; | 
|  | 79 | } else { | 
|  | 80 | return 1; | 
|  | 81 | } | 
|  | 82 | } | 
|  | 83 |  | 
|  | 84 | sub trim { | 
|  | 85 | my $s = shift; | 
|  | 86 | $s =~ s/\s+$//; | 
|  | 87 | $s =~ s/^\s+//; | 
|  | 88 | return $s; | 
|  | 89 | } | 
|  | 90 |  | 
|  | 91 | sub alpha_output { | 
|  | 92 | my ($hashref, $filename) = (@_); | 
|  | 93 |  | 
|  | 94 | return if ! scalar(keys %$hashref); | 
|  | 95 |  | 
|  | 96 | open(my $file, '>', "$filename") or die "$P: $filename: open failed - $!\n"; | 
|  | 97 | my $separator; | 
|  | 98 | foreach my $key (sort by_category keys %$hashref) { | 
|  | 99 | if ($key eq " ") { | 
|  | 100 | print $file $$hashref{$key}; | 
|  | 101 | } else { | 
|  | 102 | if (! defined $separator) { | 
|  | 103 | $separator = "\n"; | 
|  | 104 | } else { | 
|  | 105 | print $file $separator; | 
|  | 106 | } | 
|  | 107 | print $file $key . "\n"; | 
|  | 108 | foreach my $pattern (sort by_pattern split('\n', %$hashref{$key})) { | 
|  | 109 | print $file ($pattern . "\n"); | 
|  | 110 | } | 
|  | 111 | } | 
|  | 112 | } | 
|  | 113 | close($file); | 
|  | 114 | } | 
|  | 115 |  | 
|  | 116 | sub file_input { | 
|  | 117 | my ($hashref, $filename) = (@_); | 
|  | 118 |  | 
|  | 119 | my $lastline = ""; | 
|  | 120 | my $case = " "; | 
|  | 121 | $$hashref{$case} = ""; | 
|  | 122 |  | 
|  | 123 | open(my $file, '<', "$filename") or die "$P: $filename: open failed - $!\n"; | 
|  | 124 |  | 
|  | 125 | while (<$file>) { | 
|  | 126 | my $line = $_; | 
|  | 127 |  | 
|  | 128 | # Pattern line? | 
|  | 129 | if ($line =~ m/^([A-Z]):\s*(.*)/) { | 
|  | 130 | $line = $1 . ":\t" . trim($2) . "\n"; | 
|  | 131 | if ($lastline eq "") { | 
|  | 132 | $$hashref{$case} = $$hashref{$case} . $line; | 
|  | 133 | next; | 
|  | 134 | } | 
|  | 135 | $case = trim($lastline); | 
|  | 136 | exists $$hashref{$case} and die "Header '$case' already exists"; | 
|  | 137 | $$hashref{$case} = $line; | 
|  | 138 | $lastline = ""; | 
|  | 139 | next; | 
|  | 140 | } | 
|  | 141 |  | 
|  | 142 | if ($case eq " ") { | 
|  | 143 | $$hashref{$case} = $$hashref{$case} . $lastline; | 
|  | 144 | $lastline = $line; | 
|  | 145 | next; | 
|  | 146 | } | 
|  | 147 | trim($lastline) eq "" or die ("Odd non-pattern line '$lastline' for '$case'"); | 
|  | 148 | $lastline = $line; | 
|  | 149 | } | 
|  | 150 | $$hashref{$case} = $$hashref{$case} . $lastline; | 
|  | 151 | close($file); | 
|  | 152 | } | 
|  | 153 |  | 
|  | 154 | my %hash; | 
|  | 155 | my %new_hash; | 
|  | 156 |  | 
|  | 157 | file_input(\%hash, $input_file); | 
|  | 158 |  | 
|  | 159 | foreach my $type (@ARGV) { | 
|  | 160 | foreach my $key (keys %hash) { | 
|  | 161 | if ($key =~ /$type/ || $hash{$key} =~ /$type/) { | 
|  | 162 | $new_hash{$key} = $hash{$key}; | 
|  | 163 | delete $hash{$key}; | 
|  | 164 | } | 
|  | 165 | } | 
|  | 166 | } | 
|  | 167 |  | 
|  | 168 | alpha_output(\%hash, $output_file); | 
|  | 169 | alpha_output(\%new_hash, $output_section); | 
|  | 170 |  | 
|  | 171 | exit(0); |