1#!/usr/bin/perl -w 2# SPDX-License-Identifier: GPL-2.0 3 4use strict; 5use Getopt::Long qw(:config no_auto_abbrev); 6 7my $input_file = "MAINTAINERS"; 8my $output_file = "MAINTAINERS.new"; 9my $output_section = "SECTION.new"; 10my $help = 0; 11 12my $P = $0; 13 14if (!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 23if ($help != 0) { 24 usage(); 25 exit 0; 26} 27 28sub usage { 29 print <<EOT; 30usage: $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 36If <pattern match regexes> exist, then the sections that match the 37regexes are not written to the output file but are written to the 38section file. 39 40EOT 41} 42 43# sort comparison functions 44sub 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 57sub 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 84sub trim { 85 my $s = shift; 86 $s =~ s/\s+$//; 87 $s =~ s/^\s+//; 88 return $s; 89} 90 91sub 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 116sub 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 154my %hash; 155my %new_hash; 156 157file_input(\%hash, $input_file); 158 159foreach 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 168alpha_output(\%hash, $output_file); 169alpha_output(\%new_hash, $output_section); 170 171exit(0); 172