parse-maintainers.pl 3.7 KB

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