18c2ecf20Sopenharmony_ci#!/usr/bin/perl -w
28c2ecf20Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ciuse strict;
58c2ecf20Sopenharmony_ciuse Getopt::Long qw(:config no_auto_abbrev);
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_cimy $input_file = "MAINTAINERS";
88c2ecf20Sopenharmony_cimy $output_file = "MAINTAINERS.new";
98c2ecf20Sopenharmony_cimy $output_section = "SECTION.new";
108c2ecf20Sopenharmony_cimy $help = 0;
118c2ecf20Sopenharmony_cimy $order = 0;
128c2ecf20Sopenharmony_cimy $P = $0;
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ciif (!GetOptions(
158c2ecf20Sopenharmony_ci		'input=s' => \$input_file,
168c2ecf20Sopenharmony_ci		'output=s' => \$output_file,
178c2ecf20Sopenharmony_ci		'section=s' => \$output_section,
188c2ecf20Sopenharmony_ci		'order!' => \$order,
198c2ecf20Sopenharmony_ci		'h|help|usage' => \$help,
208c2ecf20Sopenharmony_ci	    )) {
218c2ecf20Sopenharmony_ci    die "$P: invalid argument - use --help if necessary\n";
228c2ecf20Sopenharmony_ci}
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ciif ($help != 0) {
258c2ecf20Sopenharmony_ci    usage();
268c2ecf20Sopenharmony_ci    exit 0;
278c2ecf20Sopenharmony_ci}
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cisub usage {
308c2ecf20Sopenharmony_ci    print <<EOT;
318c2ecf20Sopenharmony_ciusage: $P [options] <pattern matching regexes>
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci  --input => MAINTAINERS file to read (default: MAINTAINERS)
348c2ecf20Sopenharmony_ci  --output => sorted MAINTAINERS file to write (default: MAINTAINERS.new)
358c2ecf20Sopenharmony_ci  --section => new sorted MAINTAINERS file to write to (default: SECTION.new)
368c2ecf20Sopenharmony_ci  --order => Use the preferred section content output ordering (default: 0)
378c2ecf20Sopenharmony_ci    Preferred ordering of section output is:
388c2ecf20Sopenharmony_ci      M:  Person acting as a maintainer
398c2ecf20Sopenharmony_ci      R:  Person acting as a patch reviewer
408c2ecf20Sopenharmony_ci      L:  Mailing list where patches should be sent
418c2ecf20Sopenharmony_ci      S:  Maintenance status
428c2ecf20Sopenharmony_ci      W:  URI for general information
438c2ecf20Sopenharmony_ci      Q:  URI for patchwork tracking
448c2ecf20Sopenharmony_ci      B:  URI for bug tracking/submission
458c2ecf20Sopenharmony_ci      C:  URI for chat
468c2ecf20Sopenharmony_ci      P:  URI or file for subsystem specific coding styles
478c2ecf20Sopenharmony_ci      T:  SCM tree type and location
488c2ecf20Sopenharmony_ci      F:  File and directory pattern
498c2ecf20Sopenharmony_ci      X:  File and directory exclusion pattern
508c2ecf20Sopenharmony_ci      N:  File glob
518c2ecf20Sopenharmony_ci      K:  Keyword - patch content regex
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ciIf <pattern match regexes> exist, then the sections that match the
548c2ecf20Sopenharmony_ciregexes are not written to the output file but are written to the
558c2ecf20Sopenharmony_cisection file.
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ciEOT
588c2ecf20Sopenharmony_ci}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci# sort comparison functions
618c2ecf20Sopenharmony_cisub by_category($$) {
628c2ecf20Sopenharmony_ci    my ($a, $b) = @_;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci    $a = uc $a;
658c2ecf20Sopenharmony_ci    $b = uc $b;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci    # This always sorts last
688c2ecf20Sopenharmony_ci    $a =~ s/THE REST/ZZZZZZ/g;
698c2ecf20Sopenharmony_ci    $b =~ s/THE REST/ZZZZZZ/g;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci    return $a cmp $b;
728c2ecf20Sopenharmony_ci}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cisub by_pattern($$) {
758c2ecf20Sopenharmony_ci    my ($a, $b) = @_;
768c2ecf20Sopenharmony_ci    my $preferred_order = 'MRLSWQBCPTFXNK';
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci    my $a1 = uc(substr($a, 0, 1));
798c2ecf20Sopenharmony_ci    my $b1 = uc(substr($b, 0, 1));
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci    my $a_index = index($preferred_order, $a1);
828c2ecf20Sopenharmony_ci    my $b_index = index($preferred_order, $b1);
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci    $a_index = 1000 if ($a_index == -1);
858c2ecf20Sopenharmony_ci    $b_index = 1000 if ($b_index == -1);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci    if (($a1 =~ /^F$/ && $b1 =~ /^F$/) ||
888c2ecf20Sopenharmony_ci	($a1 =~ /^X$/ && $b1 =~ /^X$/)) {
898c2ecf20Sopenharmony_ci	return $a cmp $b;
908c2ecf20Sopenharmony_ci    }
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci    if ($a_index < $b_index) {
938c2ecf20Sopenharmony_ci	return -1;
948c2ecf20Sopenharmony_ci    } elsif ($a_index == $b_index) {
958c2ecf20Sopenharmony_ci	return 0;
968c2ecf20Sopenharmony_ci    } else {
978c2ecf20Sopenharmony_ci	return 1;
988c2ecf20Sopenharmony_ci    }
998c2ecf20Sopenharmony_ci}
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_cisub trim {
1028c2ecf20Sopenharmony_ci    my $s = shift;
1038c2ecf20Sopenharmony_ci    $s =~ s/\s+$//;
1048c2ecf20Sopenharmony_ci    $s =~ s/^\s+//;
1058c2ecf20Sopenharmony_ci    return $s;
1068c2ecf20Sopenharmony_ci}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_cisub alpha_output {
1098c2ecf20Sopenharmony_ci    my ($hashref, $filename) = (@_);
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci    return if ! scalar(keys %$hashref);
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci    open(my $file, '>', "$filename") or die "$P: $filename: open failed - $!\n";
1148c2ecf20Sopenharmony_ci    my $separator;
1158c2ecf20Sopenharmony_ci    foreach my $key (sort by_category keys %$hashref) {
1168c2ecf20Sopenharmony_ci	if ($key eq " ") {
1178c2ecf20Sopenharmony_ci	    print $file $$hashref{$key};
1188c2ecf20Sopenharmony_ci	} else {
1198c2ecf20Sopenharmony_ci	    if (! defined $separator) {
1208c2ecf20Sopenharmony_ci		$separator = "\n";
1218c2ecf20Sopenharmony_ci	    } else {
1228c2ecf20Sopenharmony_ci		print $file $separator;
1238c2ecf20Sopenharmony_ci	    }
1248c2ecf20Sopenharmony_ci	    print $file $key . "\n";
1258c2ecf20Sopenharmony_ci	    if ($order) {
1268c2ecf20Sopenharmony_ci		foreach my $pattern (sort by_pattern split('\n', %$hashref{$key})) {
1278c2ecf20Sopenharmony_ci		    print $file ($pattern . "\n");
1288c2ecf20Sopenharmony_ci		}
1298c2ecf20Sopenharmony_ci	    } else {
1308c2ecf20Sopenharmony_ci		foreach my $pattern (split('\n', %$hashref{$key})) {
1318c2ecf20Sopenharmony_ci		    print $file ($pattern . "\n");
1328c2ecf20Sopenharmony_ci		}
1338c2ecf20Sopenharmony_ci	    }
1348c2ecf20Sopenharmony_ci	}
1358c2ecf20Sopenharmony_ci    }
1368c2ecf20Sopenharmony_ci    close($file);
1378c2ecf20Sopenharmony_ci}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_cisub file_input {
1408c2ecf20Sopenharmony_ci    my ($hashref, $filename) = (@_);
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci    my $lastline = "";
1438c2ecf20Sopenharmony_ci    my $case = " ";
1448c2ecf20Sopenharmony_ci    $$hashref{$case} = "";
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci    open(my $file, '<', "$filename") or die "$P: $filename: open failed - $!\n";
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci    while (<$file>) {
1498c2ecf20Sopenharmony_ci        my $line = $_;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci        # Pattern line?
1528c2ecf20Sopenharmony_ci        if ($line =~ m/^([A-Z]):\s*(.*)/) {
1538c2ecf20Sopenharmony_ci            $line = $1 . ":\t" . trim($2) . "\n";
1548c2ecf20Sopenharmony_ci            if ($lastline eq "") {
1558c2ecf20Sopenharmony_ci                $$hashref{$case} = $$hashref{$case} . $line;
1568c2ecf20Sopenharmony_ci                next;
1578c2ecf20Sopenharmony_ci            }
1588c2ecf20Sopenharmony_ci            $case = trim($lastline);
1598c2ecf20Sopenharmony_ci            exists $$hashref{$case} and die "Header '$case' already exists";
1608c2ecf20Sopenharmony_ci            $$hashref{$case} = $line;
1618c2ecf20Sopenharmony_ci            $lastline = "";
1628c2ecf20Sopenharmony_ci            next;
1638c2ecf20Sopenharmony_ci        }
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci        if ($case eq " ") {
1668c2ecf20Sopenharmony_ci            $$hashref{$case} = $$hashref{$case} . $lastline;
1678c2ecf20Sopenharmony_ci            $lastline = $line;
1688c2ecf20Sopenharmony_ci            next;
1698c2ecf20Sopenharmony_ci        }
1708c2ecf20Sopenharmony_ci        trim($lastline) eq "" or die ("Odd non-pattern line '$lastline' for '$case'");
1718c2ecf20Sopenharmony_ci        $lastline = $line;
1728c2ecf20Sopenharmony_ci    }
1738c2ecf20Sopenharmony_ci    $$hashref{$case} = $$hashref{$case} . $lastline;
1748c2ecf20Sopenharmony_ci    close($file);
1758c2ecf20Sopenharmony_ci}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_cimy %hash;
1788c2ecf20Sopenharmony_cimy %new_hash;
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_cifile_input(\%hash, $input_file);
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ciforeach my $type (@ARGV) {
1838c2ecf20Sopenharmony_ci    foreach my $key (keys %hash) {
1848c2ecf20Sopenharmony_ci	if ($key =~ /$type/ || $hash{$key} =~ /$type/) {
1858c2ecf20Sopenharmony_ci	    $new_hash{$key} = $hash{$key};
1868c2ecf20Sopenharmony_ci	    delete $hash{$key};
1878c2ecf20Sopenharmony_ci	}
1888c2ecf20Sopenharmony_ci    }
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_cialpha_output(\%hash, $output_file);
1928c2ecf20Sopenharmony_cialpha_output(\%new_hash, $output_section);
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ciexit(0);
195