162306a36Sopenharmony_ci#!/usr/bin/env perl 262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0 362306a36Sopenharmony_ci 462306a36Sopenharmony_ciuse strict; 562306a36Sopenharmony_ciuse Pod::Usage; 662306a36Sopenharmony_ciuse Getopt::Long; 762306a36Sopenharmony_ciuse File::Find; 862306a36Sopenharmony_ciuse Fcntl ':mode'; 962306a36Sopenharmony_ciuse Cwd 'abs_path'; 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_cimy $help; 1262306a36Sopenharmony_cimy $man; 1362306a36Sopenharmony_cimy $debug; 1462306a36Sopenharmony_cimy $arch; 1562306a36Sopenharmony_cimy $feat; 1662306a36Sopenharmony_cimy $enable_fname; 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cimy $basename = abs_path($0); 1962306a36Sopenharmony_ci$basename =~ s,/[^/]+$,/,; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cimy $prefix=$basename . "../Documentation/features"; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci# Used only at for full features output. The script will auto-adjust 2462306a36Sopenharmony_ci# such values for the minimal possible values 2562306a36Sopenharmony_cimy $status_size = 1; 2662306a36Sopenharmony_cimy $description_size = 1; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ciGetOptions( 2962306a36Sopenharmony_ci "debug|d+" => \$debug, 3062306a36Sopenharmony_ci "dir=s" => \$prefix, 3162306a36Sopenharmony_ci 'help|?' => \$help, 3262306a36Sopenharmony_ci 'arch=s' => \$arch, 3362306a36Sopenharmony_ci 'feat=s' => \$feat, 3462306a36Sopenharmony_ci 'feature=s' => \$feat, 3562306a36Sopenharmony_ci "enable-fname" => \$enable_fname, 3662306a36Sopenharmony_ci man => \$man 3762306a36Sopenharmony_ci) or pod2usage(2); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cipod2usage(1) if $help; 4062306a36Sopenharmony_cipod2usage(-exitstatus => 0, -verbose => 2) if $man; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cipod2usage(1) if (scalar @ARGV < 1 || @ARGV > 2); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cimy ($cmd, $arg) = @ARGV; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cipod2usage(2) if ($cmd ne "current" && $cmd ne "rest" && $cmd ne "validate" 4762306a36Sopenharmony_ci && $cmd ne "ls" && $cmd ne "list"); 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cirequire Data::Dumper if ($debug); 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cimy %data; 5262306a36Sopenharmony_cimy %archs; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci# 5562306a36Sopenharmony_ci# Displays an error message, printing file name and line 5662306a36Sopenharmony_ci# 5762306a36Sopenharmony_cisub parse_error($$$$) { 5862306a36Sopenharmony_ci my ($file, $ln, $msg, $data) = @_; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci $data =~ s/\s+$/\n/; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci print STDERR "Warning: file $file#$ln:\n\t$msg"; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci if ($data ne "") { 6562306a36Sopenharmony_ci print STDERR ". Line\n\t\t$data"; 6662306a36Sopenharmony_ci } else { 6762306a36Sopenharmony_ci print STDERR "\n"; 6862306a36Sopenharmony_ci } 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci# 7262306a36Sopenharmony_ci# Parse a features file, storing its contents at %data 7362306a36Sopenharmony_ci# 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cimy $h_name = "Feature"; 7662306a36Sopenharmony_cimy $h_kconfig = "Kconfig"; 7762306a36Sopenharmony_cimy $h_description = "Description"; 7862306a36Sopenharmony_cimy $h_subsys = "Subsystem"; 7962306a36Sopenharmony_cimy $h_status = "Status"; 8062306a36Sopenharmony_cimy $h_arch = "Architecture"; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cimy $max_size_name = length($h_name); 8362306a36Sopenharmony_cimy $max_size_kconfig = length($h_kconfig); 8462306a36Sopenharmony_cimy $max_size_description = length($h_description); 8562306a36Sopenharmony_cimy $max_size_subsys = length($h_subsys); 8662306a36Sopenharmony_cimy $max_size_status = length($h_status); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cimy $max_size_arch = 0; 8962306a36Sopenharmony_cimy $max_size_arch_with_header; 9062306a36Sopenharmony_cimy $max_description_word = 0; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cisub parse_feat { 9362306a36Sopenharmony_ci my $file = $File::Find::name; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci my $mode = (stat($file))[2]; 9662306a36Sopenharmony_ci return if ($mode & S_IFDIR); 9762306a36Sopenharmony_ci return if ($file =~ m,($prefix)/arch-support.txt,); 9862306a36Sopenharmony_ci return if (!($file =~ m,arch-support.txt$,)); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci if ($enable_fname) { 10162306a36Sopenharmony_ci printf ".. FILE %s\n", abs_path($file); 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci my $subsys = ""; 10562306a36Sopenharmony_ci $subsys = $2 if ( m,.*($prefix)/([^/]+).*,); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci if (length($subsys) > $max_size_subsys) { 10862306a36Sopenharmony_ci $max_size_subsys = length($subsys); 10962306a36Sopenharmony_ci } 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci my $name; 11262306a36Sopenharmony_ci my $kconfig; 11362306a36Sopenharmony_ci my $description; 11462306a36Sopenharmony_ci my $comments = ""; 11562306a36Sopenharmony_ci my $last_status; 11662306a36Sopenharmony_ci my $ln; 11762306a36Sopenharmony_ci my %arch_table; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci print STDERR "Opening $file\n" if ($debug > 1); 12062306a36Sopenharmony_ci open IN, $file; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci while(<IN>) { 12362306a36Sopenharmony_ci $ln++; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci if (m/^\#\s+Feature\s+name:\s*(.*\S)/) { 12662306a36Sopenharmony_ci $name = $1; 12762306a36Sopenharmony_ci if (length($name) > $max_size_name) { 12862306a36Sopenharmony_ci $max_size_name = length($name); 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci next; 13162306a36Sopenharmony_ci } 13262306a36Sopenharmony_ci if (m/^\#\s+Kconfig:\s*(.*\S)/) { 13362306a36Sopenharmony_ci $kconfig = $1; 13462306a36Sopenharmony_ci if (length($kconfig) > $max_size_kconfig) { 13562306a36Sopenharmony_ci $max_size_kconfig = length($kconfig); 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci next; 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci if (m/^\#\s+description:\s*(.*\S)/) { 14062306a36Sopenharmony_ci $description = $1; 14162306a36Sopenharmony_ci if (length($description) > $max_size_description) { 14262306a36Sopenharmony_ci $max_size_description = length($description); 14362306a36Sopenharmony_ci } 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci foreach my $word (split /\s+/, $description) { 14662306a36Sopenharmony_ci if (length($word) > $max_description_word) { 14762306a36Sopenharmony_ci $max_description_word = length($word); 14862306a36Sopenharmony_ci } 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci next; 15262306a36Sopenharmony_ci } 15362306a36Sopenharmony_ci next if (m/^\\s*$/); 15462306a36Sopenharmony_ci next if (m/^\s*\-+\s*$/); 15562306a36Sopenharmony_ci next if (m/^\s*\|\s*arch\s*\|\s*status\s*\|\s*$/); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci if (m/^\#\s*(.*)/) { 15862306a36Sopenharmony_ci $comments .= "$1\n"; 15962306a36Sopenharmony_ci next; 16062306a36Sopenharmony_ci } 16162306a36Sopenharmony_ci if (m/^\s*\|\s*(\S+):\s*\|\s*(\S+)\s*\|\s*$/) { 16262306a36Sopenharmony_ci my $a = $1; 16362306a36Sopenharmony_ci my $status = $2; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci if (length($status) > $max_size_status) { 16662306a36Sopenharmony_ci $max_size_status = length($status); 16762306a36Sopenharmony_ci } 16862306a36Sopenharmony_ci if (length($a) > $max_size_arch) { 16962306a36Sopenharmony_ci $max_size_arch = length($a); 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci $status = "---" if ($status =~ m/^\.\.$/); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci $archs{$a} = 1; 17562306a36Sopenharmony_ci $arch_table{$a} = $status; 17662306a36Sopenharmony_ci next; 17762306a36Sopenharmony_ci } 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci #Everything else is an error 18062306a36Sopenharmony_ci parse_error($file, $ln, "line is invalid", $_); 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ci close IN; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci if (!$name) { 18562306a36Sopenharmony_ci parse_error($file, $ln, "Feature name not found", ""); 18662306a36Sopenharmony_ci return; 18762306a36Sopenharmony_ci } 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci parse_error($file, $ln, "Subsystem not found", "") if (!$subsys); 19062306a36Sopenharmony_ci parse_error($file, $ln, "Kconfig not found", "") if (!$kconfig); 19162306a36Sopenharmony_ci parse_error($file, $ln, "Description not found", "") if (!$description); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci if (!%arch_table) { 19462306a36Sopenharmony_ci parse_error($file, $ln, "Architecture table not found", ""); 19562306a36Sopenharmony_ci return; 19662306a36Sopenharmony_ci } 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci $data{$name}->{where} = $file; 19962306a36Sopenharmony_ci $data{$name}->{subsys} = $subsys; 20062306a36Sopenharmony_ci $data{$name}->{kconfig} = $kconfig; 20162306a36Sopenharmony_ci $data{$name}->{description} = $description; 20262306a36Sopenharmony_ci $data{$name}->{comments} = $comments; 20362306a36Sopenharmony_ci $data{$name}->{table} = \%arch_table; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci $max_size_arch_with_header = $max_size_arch + length($h_arch); 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci# 20962306a36Sopenharmony_ci# Output feature(s) for a given architecture 21062306a36Sopenharmony_ci# 21162306a36Sopenharmony_cisub output_arch_table { 21262306a36Sopenharmony_ci my $title = "Feature status on $arch architecture"; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci print "=" x length($title) . "\n"; 21562306a36Sopenharmony_ci print "$title\n"; 21662306a36Sopenharmony_ci print "=" x length($title) . "\n\n"; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci print "=" x $max_size_subsys; 21962306a36Sopenharmony_ci print " "; 22062306a36Sopenharmony_ci print "=" x $max_size_name; 22162306a36Sopenharmony_ci print " "; 22262306a36Sopenharmony_ci print "=" x $max_size_kconfig; 22362306a36Sopenharmony_ci print " "; 22462306a36Sopenharmony_ci print "=" x $max_size_status; 22562306a36Sopenharmony_ci print " "; 22662306a36Sopenharmony_ci print "=" x $max_size_description; 22762306a36Sopenharmony_ci print "\n"; 22862306a36Sopenharmony_ci printf "%-${max_size_subsys}s ", $h_subsys; 22962306a36Sopenharmony_ci printf "%-${max_size_name}s ", $h_name; 23062306a36Sopenharmony_ci printf "%-${max_size_kconfig}s ", $h_kconfig; 23162306a36Sopenharmony_ci printf "%-${max_size_status}s ", $h_status; 23262306a36Sopenharmony_ci printf "%-${max_size_description}s\n", $h_description; 23362306a36Sopenharmony_ci print "=" x $max_size_subsys; 23462306a36Sopenharmony_ci print " "; 23562306a36Sopenharmony_ci print "=" x $max_size_name; 23662306a36Sopenharmony_ci print " "; 23762306a36Sopenharmony_ci print "=" x $max_size_kconfig; 23862306a36Sopenharmony_ci print " "; 23962306a36Sopenharmony_ci print "=" x $max_size_status; 24062306a36Sopenharmony_ci print " "; 24162306a36Sopenharmony_ci print "=" x $max_size_description; 24262306a36Sopenharmony_ci print "\n"; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci foreach my $name (sort { 24562306a36Sopenharmony_ci ($data{$a}->{subsys} cmp $data{$b}->{subsys}) || 24662306a36Sopenharmony_ci ("\L$a" cmp "\L$b") 24762306a36Sopenharmony_ci } keys %data) { 24862306a36Sopenharmony_ci next if ($feat && $name ne $feat); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci my %arch_table = %{$data{$name}->{table}}; 25162306a36Sopenharmony_ci printf "%-${max_size_subsys}s ", $data{$name}->{subsys}; 25262306a36Sopenharmony_ci printf "%-${max_size_name}s ", $name; 25362306a36Sopenharmony_ci printf "%-${max_size_kconfig}s ", $data{$name}->{kconfig}; 25462306a36Sopenharmony_ci printf "%-${max_size_status}s ", $arch_table{$arch}; 25562306a36Sopenharmony_ci printf "%-s\n", $data{$name}->{description}; 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci print "=" x $max_size_subsys; 25962306a36Sopenharmony_ci print " "; 26062306a36Sopenharmony_ci print "=" x $max_size_name; 26162306a36Sopenharmony_ci print " "; 26262306a36Sopenharmony_ci print "=" x $max_size_kconfig; 26362306a36Sopenharmony_ci print " "; 26462306a36Sopenharmony_ci print "=" x $max_size_status; 26562306a36Sopenharmony_ci print " "; 26662306a36Sopenharmony_ci print "=" x $max_size_description; 26762306a36Sopenharmony_ci print "\n"; 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci# 27162306a36Sopenharmony_ci# list feature(s) for a given architecture 27262306a36Sopenharmony_ci# 27362306a36Sopenharmony_cisub list_arch_features { 27462306a36Sopenharmony_ci print "#\n# Kernel feature support matrix of the '$arch' architecture:\n#\n"; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci foreach my $name (sort { 27762306a36Sopenharmony_ci ($data{$a}->{subsys} cmp $data{$b}->{subsys}) || 27862306a36Sopenharmony_ci ("\L$a" cmp "\L$b") 27962306a36Sopenharmony_ci } keys %data) { 28062306a36Sopenharmony_ci next if ($feat && $name ne $feat); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci my %arch_table = %{$data{$name}->{table}}; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci my $status = $arch_table{$arch}; 28562306a36Sopenharmony_ci $status = " " x ((4 - length($status)) / 2) . $status; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci printf " %${max_size_subsys}s/ ", $data{$name}->{subsys}; 28862306a36Sopenharmony_ci printf "%-${max_size_name}s: ", $name; 28962306a36Sopenharmony_ci printf "%-5s| ", $status; 29062306a36Sopenharmony_ci printf "%${max_size_kconfig}s # ", $data{$name}->{kconfig}; 29162306a36Sopenharmony_ci printf " %s\n", $data{$name}->{description}; 29262306a36Sopenharmony_ci } 29362306a36Sopenharmony_ci} 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci# 29662306a36Sopenharmony_ci# Output a feature on all architectures 29762306a36Sopenharmony_ci# 29862306a36Sopenharmony_cisub output_feature { 29962306a36Sopenharmony_ci my $title = "Feature $feat"; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci print "=" x length($title) . "\n"; 30262306a36Sopenharmony_ci print "$title\n"; 30362306a36Sopenharmony_ci print "=" x length($title) . "\n\n"; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci print ":Subsystem: $data{$feat}->{subsys} \n" if ($data{$feat}->{subsys}); 30662306a36Sopenharmony_ci print ":Kconfig: $data{$feat}->{kconfig} \n" if ($data{$feat}->{kconfig}); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci my $desc = $data{$feat}->{description}; 30962306a36Sopenharmony_ci $desc =~ s/^([a-z])/\U$1/; 31062306a36Sopenharmony_ci $desc =~ s/\.?\s*//; 31162306a36Sopenharmony_ci print "\n$desc.\n\n"; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci my $com = $data{$feat}->{comments}; 31462306a36Sopenharmony_ci $com =~ s/^\s+//; 31562306a36Sopenharmony_ci $com =~ s/\s+$//; 31662306a36Sopenharmony_ci if ($com) { 31762306a36Sopenharmony_ci print "Comments\n"; 31862306a36Sopenharmony_ci print "--------\n\n"; 31962306a36Sopenharmony_ci print "$com\n\n"; 32062306a36Sopenharmony_ci } 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci print "=" x $max_size_arch_with_header; 32362306a36Sopenharmony_ci print " "; 32462306a36Sopenharmony_ci print "=" x $max_size_status; 32562306a36Sopenharmony_ci print "\n"; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci printf "%-${max_size_arch}s ", $h_arch; 32862306a36Sopenharmony_ci printf "%-${max_size_status}s", $h_status . "\n"; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci print "=" x $max_size_arch_with_header; 33162306a36Sopenharmony_ci print " "; 33262306a36Sopenharmony_ci print "=" x $max_size_status; 33362306a36Sopenharmony_ci print "\n"; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci my %arch_table = %{$data{$feat}->{table}}; 33662306a36Sopenharmony_ci foreach my $arch (sort keys %arch_table) { 33762306a36Sopenharmony_ci printf "%-${max_size_arch}s ", $arch; 33862306a36Sopenharmony_ci printf "%-${max_size_status}s\n", $arch_table{$arch}; 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci print "=" x $max_size_arch_with_header; 34262306a36Sopenharmony_ci print " "; 34362306a36Sopenharmony_ci print "=" x $max_size_status; 34462306a36Sopenharmony_ci print "\n"; 34562306a36Sopenharmony_ci} 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci# 34862306a36Sopenharmony_ci# Output all features for all architectures 34962306a36Sopenharmony_ci# 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_cisub matrix_lines($$$) { 35262306a36Sopenharmony_ci my $desc_size = shift; 35362306a36Sopenharmony_ci my $status_size = shift; 35462306a36Sopenharmony_ci my $header = shift; 35562306a36Sopenharmony_ci my $fill; 35662306a36Sopenharmony_ci my $ln_marker; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci if ($header) { 35962306a36Sopenharmony_ci $ln_marker = "="; 36062306a36Sopenharmony_ci } else { 36162306a36Sopenharmony_ci $ln_marker = "-"; 36262306a36Sopenharmony_ci } 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci $fill = $ln_marker; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci print "+"; 36762306a36Sopenharmony_ci print $fill x $max_size_name; 36862306a36Sopenharmony_ci print "+"; 36962306a36Sopenharmony_ci print $fill x $desc_size; 37062306a36Sopenharmony_ci print "+"; 37162306a36Sopenharmony_ci print $ln_marker x $status_size; 37262306a36Sopenharmony_ci print "+\n"; 37362306a36Sopenharmony_ci} 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_cisub output_matrix { 37662306a36Sopenharmony_ci my $title = "Feature status on all architectures"; 37762306a36Sopenharmony_ci my $notcompat = "Not compatible"; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci print "=" x length($title) . "\n"; 38062306a36Sopenharmony_ci print "$title\n"; 38162306a36Sopenharmony_ci print "=" x length($title) . "\n\n"; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci my $desc_title = "$h_kconfig / $h_description"; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci my $desc_size = $max_size_kconfig + 4; 38662306a36Sopenharmony_ci if (!$description_size) { 38762306a36Sopenharmony_ci $desc_size = $max_size_description if ($max_size_description > $desc_size); 38862306a36Sopenharmony_ci } else { 38962306a36Sopenharmony_ci $desc_size = $description_size if ($description_size > $desc_size); 39062306a36Sopenharmony_ci } 39162306a36Sopenharmony_ci $desc_size = $max_description_word if ($max_description_word > $desc_size); 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci $desc_size = length($desc_title) if (length($desc_title) > $desc_size); 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci $max_size_status = length($notcompat) if (length($notcompat) > $max_size_status); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci # Ensure that the status will fit 39862306a36Sopenharmony_ci my $min_status_size = $max_size_status + $max_size_arch + 6; 39962306a36Sopenharmony_ci $status_size = $min_status_size if ($status_size < $min_status_size); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci my $cur_subsys = ""; 40362306a36Sopenharmony_ci foreach my $name (sort { 40462306a36Sopenharmony_ci ($data{$a}->{subsys} cmp $data{$b}->{subsys}) or 40562306a36Sopenharmony_ci ("\L$a" cmp "\L$b") 40662306a36Sopenharmony_ci } keys %data) { 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci if ($cur_subsys ne $data{$name}->{subsys}) { 40962306a36Sopenharmony_ci if ($cur_subsys ne "") { 41062306a36Sopenharmony_ci printf "\n"; 41162306a36Sopenharmony_ci } 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci $cur_subsys = $data{$name}->{subsys}; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci my $title = "Subsystem: $cur_subsys"; 41662306a36Sopenharmony_ci print "$title\n"; 41762306a36Sopenharmony_ci print "=" x length($title) . "\n\n"; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci matrix_lines($desc_size, $status_size, 0); 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci printf "|%-${max_size_name}s", $h_name; 42362306a36Sopenharmony_ci printf "|%-${desc_size}s", $desc_title; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci printf "|%-${status_size}s|\n", "Status per architecture"; 42662306a36Sopenharmony_ci matrix_lines($desc_size, $status_size, 1); 42762306a36Sopenharmony_ci } 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci my %arch_table = %{$data{$name}->{table}}; 43062306a36Sopenharmony_ci my $cur_status = ""; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci my (@lines, @descs); 43362306a36Sopenharmony_ci my $line = ""; 43462306a36Sopenharmony_ci foreach my $arch (sort { 43562306a36Sopenharmony_ci ($arch_table{$b} cmp $arch_table{$a}) or 43662306a36Sopenharmony_ci ("\L$a" cmp "\L$b") 43762306a36Sopenharmony_ci } keys %arch_table) { 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci my $status = $arch_table{$arch}; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci if ($status eq "---") { 44262306a36Sopenharmony_ci $status = $notcompat; 44362306a36Sopenharmony_ci } 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci if ($status ne $cur_status) { 44662306a36Sopenharmony_ci if ($line ne "") { 44762306a36Sopenharmony_ci push @lines, $line; 44862306a36Sopenharmony_ci $line = ""; 44962306a36Sopenharmony_ci } 45062306a36Sopenharmony_ci $line = "- **" . $status . "**: " . $arch; 45162306a36Sopenharmony_ci } elsif (length($line) + length ($arch) + 2 < $status_size) { 45262306a36Sopenharmony_ci $line .= ", " . $arch; 45362306a36Sopenharmony_ci } else { 45462306a36Sopenharmony_ci push @lines, $line; 45562306a36Sopenharmony_ci $line = " " . $arch; 45662306a36Sopenharmony_ci } 45762306a36Sopenharmony_ci $cur_status = $status; 45862306a36Sopenharmony_ci } 45962306a36Sopenharmony_ci push @lines, $line if ($line ne ""); 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci my $description = $data{$name}->{description}; 46262306a36Sopenharmony_ci while (length($description) > $desc_size) { 46362306a36Sopenharmony_ci my $d = substr $description, 0, $desc_size; 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci # Ensure that it will end on a space 46662306a36Sopenharmony_ci # if it can't, it means that the size is too small 46762306a36Sopenharmony_ci # Instead of aborting it, let's print what we have 46862306a36Sopenharmony_ci if (!($d =~ s/^(.*)\s+.*/$1/)) { 46962306a36Sopenharmony_ci $d = substr $d, 0, -1; 47062306a36Sopenharmony_ci push @descs, "$d\\"; 47162306a36Sopenharmony_ci $description =~ s/^\Q$d\E//; 47262306a36Sopenharmony_ci } else { 47362306a36Sopenharmony_ci push @descs, $d; 47462306a36Sopenharmony_ci $description =~ s/^\Q$d\E\s+//; 47562306a36Sopenharmony_ci } 47662306a36Sopenharmony_ci } 47762306a36Sopenharmony_ci push @descs, $description; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci # Ensure that the full description will be printed 48062306a36Sopenharmony_ci push @lines, "" while (scalar(@lines) < 2 + scalar(@descs)); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci my $ln = 0; 48362306a36Sopenharmony_ci for my $line(@lines) { 48462306a36Sopenharmony_ci if (!$ln) { 48562306a36Sopenharmony_ci printf "|%-${max_size_name}s", $name; 48662306a36Sopenharmony_ci printf "|%-${desc_size}s", "``" . $data{$name}->{kconfig} . "``"; 48762306a36Sopenharmony_ci } elsif ($ln >= 2 && scalar(@descs)) { 48862306a36Sopenharmony_ci printf "|%-${max_size_name}s", ""; 48962306a36Sopenharmony_ci printf "|%-${desc_size}s", shift @descs; 49062306a36Sopenharmony_ci } else { 49162306a36Sopenharmony_ci printf "|%-${max_size_name}s", ""; 49262306a36Sopenharmony_ci printf "|%-${desc_size}s", ""; 49362306a36Sopenharmony_ci } 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci printf "|%-${status_size}s|\n", $line; 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci $ln++; 49862306a36Sopenharmony_ci } 49962306a36Sopenharmony_ci matrix_lines($desc_size, $status_size, 0); 50062306a36Sopenharmony_ci } 50162306a36Sopenharmony_ci} 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci# 50562306a36Sopenharmony_ci# Parses all feature files located at $prefix dir 50662306a36Sopenharmony_ci# 50762306a36Sopenharmony_cifind({wanted =>\&parse_feat, no_chdir => 1}, $prefix); 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ciprint STDERR Data::Dumper->Dump([\%data], [qw(*data)]) if ($debug); 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci# 51262306a36Sopenharmony_ci# Handles the command 51362306a36Sopenharmony_ci# 51462306a36Sopenharmony_ciif ($cmd eq "current") { 51562306a36Sopenharmony_ci $arch = qx(uname -m | sed 's/x86_64/x86/' | sed 's/i386/x86/'); 51662306a36Sopenharmony_ci $arch =~s/\s+$//; 51762306a36Sopenharmony_ci} 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ciif ($cmd eq "ls" or $cmd eq "list") { 52062306a36Sopenharmony_ci if (!$arch) { 52162306a36Sopenharmony_ci $arch = qx(uname -m | sed 's/x86_64/x86/' | sed 's/i386/x86/'); 52262306a36Sopenharmony_ci $arch =~s/\s+$//; 52362306a36Sopenharmony_ci } 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci list_arch_features; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci exit; 52862306a36Sopenharmony_ci} 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ciif ($cmd ne "validate") { 53162306a36Sopenharmony_ci if ($arch) { 53262306a36Sopenharmony_ci output_arch_table; 53362306a36Sopenharmony_ci } elsif ($feat) { 53462306a36Sopenharmony_ci output_feature; 53562306a36Sopenharmony_ci } else { 53662306a36Sopenharmony_ci output_matrix; 53762306a36Sopenharmony_ci } 53862306a36Sopenharmony_ci} 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci__END__ 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci=head1 NAME 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ciget_feat.pl - parse the Linux Feature files and produce a ReST book. 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci=head1 SYNOPSIS 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ciB<get_feat.pl> [--debug] [--man] [--help] [--dir=<dir>] [--arch=<arch>] 54962306a36Sopenharmony_ci [--feature=<feature>|--feat=<feature>] <COMAND> [<ARGUMENT>] 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ciWhere <COMMAND> can be: 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci=over 8 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ciB<current> - output table in ReST compatible ASCII format 55662306a36Sopenharmony_ci with features for this machine's architecture 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ciB<rest> - output table(s) in ReST compatible ASCII format 55962306a36Sopenharmony_ci with features in ReST markup language. The output 56062306a36Sopenharmony_ci is affected by --arch or --feat/--feature flags. 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ciB<validate> - validate the contents of the files under 56362306a36Sopenharmony_ci Documentation/features. 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ciB<ls> or B<list> - list features for this machine's architecture, 56662306a36Sopenharmony_ci using an easier to parse format. 56762306a36Sopenharmony_ci The output is affected by --arch flag. 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci=back 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci=head1 OPTIONS 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci=over 8 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci=item B<--arch> 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ciOutput features for an specific architecture, optionally filtering for 57862306a36Sopenharmony_cia single specific feature. 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci=item B<--feat> or B<--feature> 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ciOutput features for a single specific feature. 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci=item B<--dir> 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ciChanges the location of the Feature files. By default, it uses 58762306a36Sopenharmony_cithe Documentation/features directory. 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci=item B<--enable-fname> 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ciPrints the file name of the feature files. This can be used in order to 59262306a36Sopenharmony_citrack dependencies during documentation build. 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci=item B<--debug> 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ciPut the script in verbose mode, useful for debugging. Can be called multiple 59762306a36Sopenharmony_citimes, to increase verbosity. 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci=item B<--help> 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ciPrints a brief help message and exits. 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci=item B<--man> 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ciPrints the manual page and exits. 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci=back 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci=head1 DESCRIPTION 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ciParse the Linux feature files from Documentation/features (by default), 61262306a36Sopenharmony_cioptionally producing results at ReST format. 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ciIt supports output data per architecture, per feature or a 61562306a36Sopenharmony_cifeature x arch matrix. 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ciWhen used with B<rest> command, it will use either one of the tree formats: 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ciIf neither B<--arch> or B<--feature> arguments are used, it will output a 62062306a36Sopenharmony_cimatrix with features per architecture. 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ciIf B<--arch> argument is used, it will output the features availability for 62362306a36Sopenharmony_cia given architecture. 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ciIf B<--feat> argument is used, it will output the content of the feature 62662306a36Sopenharmony_cifile using ReStructured Text markup. 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci=head1 BUGS 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ciReport bugs to Mauro Carvalho Chehab <mchehab+samsung@kernel.org> 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci=head1 COPYRIGHT 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ciCopyright (c) 2019 by Mauro Carvalho Chehab <mchehab+samsung@kernel.org>. 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ciLicense GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>. 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ciThis is free software: you are free to change and redistribute it. 63962306a36Sopenharmony_ciThere is NO WARRANTY, to the extent permitted by law. 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci=cut 642