From ae5b17e464146ddb8fee744fa2150922d6072916 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 2 Nov 2020 19:06:37 +0200 Subject: scripts: kernel-doc: Restore anonymous enum parsing The commit d38c8cfb0571 ("scripts: kernel-doc: add support for typedef enum") broke anonymous enum parsing. Restore it by relying on members rather than its name. Fixes: d38c8cfb0571 ("scripts: kernel-doc: add support for typedef enum") Reported-by: kernel test robot Signed-off-by: Andy Shevchenko Reviewed-by: Mauro Carvalho Chehab Cc: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/20201102170637.36138-1-andriy.shevchenko@linux.intel.com Signed-off-by: Jonathan Corbet --- scripts/kernel-doc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index f699cf05d409..9b6ddeb097e9 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1390,7 +1390,7 @@ sub dump_enum($$) { $members = $2; } - if ($declaration_name) { + if ($members) { my %_members; $members =~ s/\s+$//; -- cgit v1.2.3 From 52a4be3ffc0fe2cc6af779c35525846cda7dea28 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 30 Nov 2020 16:36:30 +0100 Subject: scripts: get_feat.pl: add a script to handle Documentation/features The Documentation/features contains a set of parseable files. It is not worth converting them to ReST format, as they're useful the way it is. It is, however, interesting to parse them and produce output on different formats: 1) Output the contents of a feature in ReST format; 2) Output what features a given architecture supports; 3) Output a matrix with features x architectures. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/8b0c1ad06d689283a6d78c4ccd188a02c3acc0de.1606748711.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet --- scripts/get_feat.pl | 474 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 474 insertions(+) create mode 100755 scripts/get_feat.pl (limited to 'scripts') diff --git a/scripts/get_feat.pl b/scripts/get_feat.pl new file mode 100755 index 000000000000..79d83595addd --- /dev/null +++ b/scripts/get_feat.pl @@ -0,0 +1,474 @@ +#!/usr/bin/perl +# SPDX-License-Identifier: GPL-2.0 + +use strict; +use Pod::Usage; +use Getopt::Long; +use File::Find; +use Fcntl ':mode'; + +my $help; +my $man; +my $debug; +my $arch; +my $feat; +my $prefix="Documentation/features"; + +GetOptions( + "debug|d+" => \$debug, + "dir=s" => \$prefix, + 'help|?' => \$help, + 'arch=s' => \$arch, + 'feat=s' => \$feat, + man => \$man +) or pod2usage(2); + +pod2usage(1) if $help; +pod2usage(-exitstatus => 0, -verbose => 2) if $man; + +pod2usage(2) if (scalar @ARGV < 1 || @ARGV > 2); + +my ($cmd, $arg) = @ARGV; + +pod2usage(2) if ($cmd ne "current" && $cmd ne "rest" && $cmd ne "validate"); + +require Data::Dumper if ($debug); + +my %data; +my %archs; + +# +# Displays an error message, printing file name and line +# +sub parse_error($$$$) { + my ($file, $ln, $msg, $data) = @_; + + $data =~ s/\s+$/\n/; + + print STDERR "Warning: file $file#$ln:\n\t$msg"; + + if ($data ne "") { + print STDERR ". Line\n\t\t$data"; + } else { + print STDERR "\n"; + } +} + +# +# Parse a features file, storing its contents at %data +# + +my $h_name = "Feature"; +my $h_kconfig = "Kconfig"; +my $h_description = "Description"; +my $h_subsys = "Subsystem"; +my $h_status = "Status"; +my $h_arch = "Architecture"; + +my $max_size_name = length($h_name); +my $max_size_kconfig = length($h_kconfig); +my $max_size_description = length($h_description); +my $max_size_subsys = length($h_subsys); +my $max_size_status = length($h_status); +my $max_size_arch = length($h_arch); + +sub parse_feat { + my $file = $File::Find::name; + + my $mode = (stat($file))[2]; + return if ($mode & S_IFDIR); + return if ($file =~ m,($prefix)/arch-support.txt,); + return if (!($file =~ m,arch-support.txt$,)); + + my $subsys = ""; + $subsys = $2 if ( m,.*($prefix)/([^/]+).*,); + + if (length($subsys) > $max_size_subsys) { + $max_size_subsys = length($subsys); + } + + my $name; + my $kconfig; + my $description; + my $comments = ""; + my $last_status; + my $ln; + my %arch_table; + + print STDERR "Opening $file\n" if ($debug > 1); + open IN, $file; + + while() { + $ln++; + + if (m/^\#\s+Feature\s+name:\s*(.*\S)/) { + $name = $1; + if (length($name) > $max_size_name) { + $max_size_name = length($name); + } + next; + } + if (m/^\#\s+Kconfig:\s*(.*\S)/) { + $kconfig = $1; + if (length($kconfig) > $max_size_kconfig) { + $max_size_kconfig = length($kconfig); + } + next; + } + if (m/^\#\s+description:\s*(.*\S)/) { + $description = $1; + if (length($description) > $max_size_description) { + $max_size_description = length($description); + } + next; + } + next if (m/^\\s*$/); + next if (m/^\s*\-+\s*$/); + next if (m/^\s*\|\s*arch\s*\|\s*status\s*\|\s*$/); + + if (m/^\#\s*(.*)/) { + $comments .= "$1\n"; + next; + } + if (m/^\s*\|\s*(\S+):\s*\|\s*(\S+)\s*\|\s*$/) { + my $a = $1; + my $status = $2; + + if (length($status) > $max_size_status) { + $max_size_status = length($status); + } + if (length($a) > $max_size_arch) { + $max_size_arch = length($a); + } + + $status = "---" if ($status =~ m/^\.\.$/); + + $archs{$a} = 1; + $arch_table{$a} = $status; + next; + } + + #Everything else is an error + parse_error($file, $ln, "line is invalid", $_); + } + close IN; + + if (!$name) { + parse_error($file, $ln, "Feature name not found", ""); + return; + } + + parse_error($file, $ln, "Subsystem not found", "") if (!$subsys); + parse_error($file, $ln, "Kconfig not found", "") if (!$kconfig); + parse_error($file, $ln, "Description not found", "") if (!$description); + + if (!%arch_table) { + parse_error($file, $ln, "Architecture table not found", ""); + return; + } + + $data{$name}->{where} = $file; + $data{$name}->{subsys} = $subsys; + $data{$name}->{kconfig} = $kconfig; + $data{$name}->{description} = $description; + $data{$name}->{comments} = $comments; + $data{$name}->{table} = \%arch_table; +} + +# +# Output feature(s) for a given architecture +# +sub output_arch_table { + my $title = "Feature status on $arch architecture"; + + print "=" x length($title) . "\n"; + print "$title\n"; + print "=" x length($title) . "\n\n"; + + print "=" x $max_size_subsys; + print " "; + print "=" x $max_size_name; + print " "; + print "=" x $max_size_kconfig; + print " "; + print "=" x $max_size_status; + print " "; + print "=" x $max_size_description; + print "\n"; + printf "%-${max_size_subsys}s ", $h_subsys; + printf "%-${max_size_name}s ", $h_name; + printf "%-${max_size_kconfig}s ", $h_kconfig; + printf "%-${max_size_status}s ", $h_status; + printf "%-${max_size_description}s\n", $h_description; + print "=" x $max_size_subsys; + print " "; + print "=" x $max_size_name; + print " "; + print "=" x $max_size_kconfig; + print " "; + print "=" x $max_size_status; + print " "; + print "=" x $max_size_description; + print "\n"; + + foreach my $name (sort { + ($data{$a}->{subsys} cmp $data{$b}->{subsys}) || + ($data{$a}->{name} cmp $data{$b}->{name}) + } keys %data) { + next if ($feat && $name ne $feat); + + my %arch_table = %{$data{$name}->{table}}; + printf "%-${max_size_subsys}s ", $data{$name}->{subsys}; + printf "%-${max_size_name}s ", $name; + printf "%-${max_size_kconfig}s ", $data{$name}->{kconfig}; + printf "%-${max_size_status}s ", $arch_table{$arch}; + printf "%-${max_size_description}s\n", $data{$name}->{description}; + } + + print "=" x $max_size_subsys; + print " "; + print "=" x $max_size_name; + print " "; + print "=" x $max_size_kconfig; + print " "; + print "=" x $max_size_status; + print " "; + print "=" x $max_size_description; + print "\n"; +} + +# +# Output a feature on all architectures +# +sub output_feature { + my $title = "Feature $feat"; + + print "=" x length($title) . "\n"; + print "$title\n"; + print "=" x length($title) . "\n\n"; + + print ":Subsystem: $data{$feat}->{subsys} \n" if ($data{$feat}->{subsys}); + print ":Kconfig: $data{$feat}->{kconfig} \n" if ($data{$feat}->{kconfig}); + + my $desc = $data{$feat}->{description}; + $desc =~ s/^([a-z])/\U$1/; + $desc =~ s/\.?\s*//; + print "\n$desc.\n\n"; + + my $com = $data{$feat}->{comments}; + $com =~ s/^\s+//; + $com =~ s/\s+$//; + if ($com) { + print "Comments\n"; + print "--------\n\n"; + print "$com\n\n"; + } + + print "=" x $max_size_arch; + print " "; + print "=" x $max_size_status; + print "\n"; + + printf "%-${max_size_arch}s ", $h_arch; + printf "%-${max_size_status}s", $h_status . "\n"; + + print "=" x $max_size_arch; + print " "; + print "=" x $max_size_status; + print "\n"; + + my %arch_table = %{$data{$feat}->{table}}; + foreach my $arch (sort keys %arch_table) { + printf "%-${max_size_arch}s ", $arch; + printf "%-${max_size_status}s\n", $arch_table{$arch}; + } + + print "=" x $max_size_arch; + print " "; + print "=" x $max_size_status; + print "\n"; +} + +# +# Output all features for all architectures +# + +sub matrix_lines { + print "=" x $max_size_subsys; + print " "; + print "=" x $max_size_name; + print " "; + + foreach my $arch (sort keys %archs) { + my $len = $max_size_status; + + $len = length($arch) if ($len < length($arch)); + + print "=" x $len; + print " "; + } + print "=" x $max_size_kconfig; + print " "; + print "=" x $max_size_description; + print "\n"; +} + +sub output_matrix { + + my $title = "Feature List (feature x architecture)"; + + print "=" x length($title) . "\n"; + print "$title\n"; + print "=" x length($title) . "\n\n"; + + matrix_lines; + + printf "%-${max_size_subsys}s ", $h_subsys; + printf "%-${max_size_name}s ", $h_name; + + foreach my $arch (sort keys %archs) { + printf "%-${max_size_status}s ", $arch; + } + printf "%-${max_size_kconfig}s ", $h_kconfig; + printf "%-${max_size_description}s\n", $h_description; + + matrix_lines; + + foreach my $name (sort { + ($data{$a}->{subsys} cmp $data{$b}->{subsys}) || + ($data{$a}->{name} cmp $data{$b}->{name}) + } keys %data) { + printf "%-${max_size_subsys}s ", $data{$name}->{subsys}; + printf "%-${max_size_name}s ", $name; + + my %arch_table = %{$data{$name}->{table}}; + + foreach my $arch (sort keys %arch_table) { + my $len = $max_size_status; + + $len = length($arch) if ($len < length($arch)); + + printf "%-${len}s ", $arch_table{$arch}; + } + printf "%-${max_size_kconfig}s ", $data{$name}->{kconfig}; + printf "%-${max_size_description}s\n", $data{$name}->{description}; + } + + matrix_lines; +} + + +# +# Parses all feature files located at $prefix dir +# +find({wanted =>\&parse_feat, no_chdir => 1}, $prefix); + +print STDERR Data::Dumper->Dump([\%data], [qw(*data)]) if ($debug); + +# +# Handles the command +# +if ($cmd eq "current") { + $arch = qx(uname -m | sed 's/x86_64/x86/' | sed 's/i386/x86/'); + $arch =~s/\s+$//; +} + +if ($cmd ne "validate") { + if ($arch) { + output_arch_table; + } elsif ($feat) { + output_feature; + } else { + output_matrix; + } +} + +__END__ + +=head1 NAME + +get_feat.pl - parse the Linux Feature files and produce a ReST book. + +=head1 SYNOPSIS + +B [--debug] [--man] [--help] [--dir=] + [--arch=] [--feat=] [] + +Where can be: + +=over 8 + +B - output features for this machine's architecture + +B - output features in ReST markup language + +B - validate the feature contents + +=back + +=head1 OPTIONS + +=over 8 + +=item B<--arch> + +Output features for an specific architecture, optionally filtering for +a single specific feature. + +=item B<--feat> + +Output features for a single specific architecture. + +=item B<--dir> + +Changes the location of the Feature files. By default, it uses +the Documentation/features directory. + +=item B<--debug> + +Put the script in verbose mode, useful for debugging. Can be called multiple +times, to increase verbosity. + +=item B<--help> + +Prints a brief help message and exits. + +=item B<--man> + +Prints the manual page and exits. + +=back + +=head1 DESCRIPTION + +Parse the Linux feature files from Documentation/features (by default), +optionally producing results at ReST format. + +It supports output data per architecture, per feature or a +feature x arch matrix. + +When used with B command, it will use either one of the tree formats: + +If neither B<--arch> or B<--feature> arguments are used, it will output a +matrix with features per architecture. + +If B<--arch> argument is used, it will output the features availability for +a given architecture. + +If B<--feat> argument is used, it will output the content of the feature +file using ReStructured Text markup. + +=head1 BUGS + +Report bugs to Mauro Carvalho Chehab + +=head1 COPYRIGHT + +Copyright (c) 2019 by Mauro Carvalho Chehab . + +License GPLv2: GNU GPL version 2 . + +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. + +=cut -- cgit v1.2.3 From ba813f7c2dc894eebcb3f8a66c0e9e26e53a4923 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 30 Nov 2020 16:36:31 +0100 Subject: scripts: get_feat.pl: improve matrix output Instead of producing a too wide table, let's split it per subsystem, and use a better notation in order to make easier for the reader to identify how a feature is supported on multiple architectures. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/9c3e8c813e8146c5c30e10fa75974f8fbfe6016a.1606748711.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet --- scripts/get_feat.pl | 113 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 43 deletions(-) (limited to 'scripts') diff --git a/scripts/get_feat.pl b/scripts/get_feat.pl index 79d83595addd..7b92ebab7ddd 100755 --- a/scripts/get_feat.pl +++ b/scripts/get_feat.pl @@ -293,68 +293,95 @@ sub output_feature { # Output all features for all architectures # -sub matrix_lines { - print "=" x $max_size_subsys; - print " "; - print "=" x $max_size_name; - print " "; - - foreach my $arch (sort keys %archs) { - my $len = $max_size_status; - - $len = length($arch) if ($len < length($arch)); +sub matrix_lines($$) { + my $partial = shift; + my $header = shift; + my $split; + my $fill; + my $ln_marker; + + if ($header) { + $ln_marker = "="; + } else { + $ln_marker = "-"; + } - print "=" x $len; - print " "; + if ($partial) { + $split = "|"; + $fill = " "; + } else { + $split = "+"; + $fill = $ln_marker; } - print "=" x $max_size_kconfig; - print " "; - print "=" x $max_size_description; - print "\n"; + + print $split; + print $fill x $max_size_name; + print $split; + print $fill x $max_size_kconfig; + print $split; + print $fill x $max_size_description; + print "+"; + print $ln_marker x $max_size_arch; + print "+"; + print $ln_marker x $max_size_status; + print "+\n"; } sub output_matrix { - - my $title = "Feature List (feature x architecture)"; + my $title = "Feature status on all architectures"; print "=" x length($title) . "\n"; print "$title\n"; print "=" x length($title) . "\n\n"; - matrix_lines; - - printf "%-${max_size_subsys}s ", $h_subsys; - printf "%-${max_size_name}s ", $h_name; + my $cur_subsys = ""; + foreach my $name (sort { + ($data{$a}->{subsys} cmp $data{$b}->{subsys}) or + ($a cmp $b) + } keys %data) { - foreach my $arch (sort keys %archs) { - printf "%-${max_size_status}s ", $arch; - } - printf "%-${max_size_kconfig}s ", $h_kconfig; - printf "%-${max_size_description}s\n", $h_description; + if ($cur_subsys ne $data{$name}->{subsys}) { + if ($cur_subsys ne "") { + printf "\n"; + } - matrix_lines; + $cur_subsys = $data{$name}->{subsys}; - foreach my $name (sort { - ($data{$a}->{subsys} cmp $data{$b}->{subsys}) || - ($data{$a}->{name} cmp $data{$b}->{name}) - } keys %data) { - printf "%-${max_size_subsys}s ", $data{$name}->{subsys}; - printf "%-${max_size_name}s ", $name; + my $title = "Subsystem: $cur_subsys"; + print "$title\n"; + print "=" x length($title) . "\n\n"; - my %arch_table = %{$data{$name}->{table}}; + matrix_lines(0, 0); + printf "|%-${max_size_name}s", $h_name; + printf "|%-${max_size_kconfig}s", $h_kconfig; + printf "|%-${max_size_description}s", $h_description; - foreach my $arch (sort keys %arch_table) { - my $len = $max_size_status; + printf "|%-${max_size_arch}s", $h_arch; + printf "|%-${max_size_status}s|\n", $h_status; - $len = length($arch) if ($len < length($arch)); + matrix_lines(0, 1); + } - printf "%-${len}s ", $arch_table{$arch}; + my %arch_table = %{$data{$name}->{table}}; + my $first = 1; + foreach my $arch (sort keys %arch_table) { + if ($first) { + printf "|%-${max_size_name}s", $name; + printf "|%-${max_size_kconfig}s", $data{$name}->{kconfig}; + printf "|%-${max_size_description}s", $data{$name}->{description}; + $first = 0; + } else { + matrix_lines(1, 0); + + printf "|%-${max_size_name}s", ""; + printf "|%-${max_size_kconfig}s", ""; + printf "|%-${max_size_description}s", ""; + } + printf "|%-${max_size_arch}s", $arch; + printf "|%-${max_size_status}s|\n", $arch_table{$arch}; } - printf "%-${max_size_kconfig}s ", $data{$name}->{kconfig}; - printf "%-${max_size_description}s\n", $data{$name}->{description}; + matrix_lines(0, 0); } - - matrix_lines; } -- cgit v1.2.3 From ca908577790fd0dc3070813b752d7eb7f74e609f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 30 Nov 2020 16:36:32 +0100 Subject: scripts: get_feat.pl: use its implementation for list-arch.sh Add support for the same output format as the bash script, and use its implementation instead of the previous one. I opted to do such patch in order to have a single script responsible for parsing Documentation/features and produce different outputs. As someone may rely on the past format, which is easy to parse it, get_feat.pl now gains a new command with the same output format as the previous script. As a side effect, the perl script is a lot faster, as it reads each file only once, instead of parsing files several times via a for command and grep commands inside it. This patch also changes the features list order to be case-insensitive, in order to better match the output of the existing script. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/a97f49677805ad4e6b982d02c0db8c9dfbbd20a6.1606748711.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet --- scripts/get_feat.pl | 77 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 13 deletions(-) (limited to 'scripts') diff --git a/scripts/get_feat.pl b/scripts/get_feat.pl index 7b92ebab7ddd..81d1b78d65c9 100755 --- a/scripts/get_feat.pl +++ b/scripts/get_feat.pl @@ -6,13 +6,18 @@ use Pod::Usage; use Getopt::Long; use File::Find; use Fcntl ':mode'; +use Cwd 'abs_path'; my $help; my $man; my $debug; my $arch; my $feat; -my $prefix="Documentation/features"; + +my $basename = abs_path($0); +$basename =~ s,/[^/]+$,/,; + +my $prefix=$basename . "../Documentation/features"; GetOptions( "debug|d+" => \$debug, @@ -20,17 +25,19 @@ GetOptions( 'help|?' => \$help, 'arch=s' => \$arch, 'feat=s' => \$feat, + 'feature=s' => \$feat, man => \$man ) or pod2usage(2); pod2usage(1) if $help; pod2usage(-exitstatus => 0, -verbose => 2) if $man; -pod2usage(2) if (scalar @ARGV < 1 || @ARGV > 2); +pod2usage(1) if (scalar @ARGV < 1 || @ARGV > 2); my ($cmd, $arg) = @ARGV; -pod2usage(2) if ($cmd ne "current" && $cmd ne "rest" && $cmd ne "validate"); +pod2usage(2) if ($cmd ne "current" && $cmd ne "rest" && $cmd ne "validate" + && $cmd ne "ls" && $cmd ne "list"); require Data::Dumper if ($debug); @@ -213,7 +220,7 @@ sub output_arch_table { foreach my $name (sort { ($data{$a}->{subsys} cmp $data{$b}->{subsys}) || - ($data{$a}->{name} cmp $data{$b}->{name}) + ("\L$a" cmp "\L$b") } keys %data) { next if ($feat && $name ne $feat); @@ -222,7 +229,7 @@ sub output_arch_table { printf "%-${max_size_name}s ", $name; printf "%-${max_size_kconfig}s ", $data{$name}->{kconfig}; printf "%-${max_size_status}s ", $arch_table{$arch}; - printf "%-${max_size_description}s\n", $data{$name}->{description}; + printf "%-s\n", $data{$name}->{description}; } print "=" x $max_size_subsys; @@ -237,6 +244,31 @@ sub output_arch_table { print "\n"; } +# +# list feature(s) for a given architecture +# +sub list_arch_features { + print "#\n# Kernel feature support matrix of the '$arch' architecture:\n#\n"; + + foreach my $name (sort { + ($data{$a}->{subsys} cmp $data{$b}->{subsys}) || + ("\L$a" cmp "\L$b") + } keys %data) { + next if ($feat && $name ne $feat); + + my %arch_table = %{$data{$name}->{table}}; + + my $status = $arch_table{$arch}; + $status = " " x ((4 - length($status)) / 2) . $status; + + printf " %${max_size_subsys}s/ ", $data{$name}->{subsys}; + printf "%-${max_size_name}s: ", $name; + printf "%-5s| ", $status; + printf "%${max_size_kconfig}s # ", $data{$name}->{kconfig}; + printf " %s\n", $data{$name}->{description}; + } +} + # # Output a feature on all architectures # @@ -337,7 +369,7 @@ sub output_matrix { my $cur_subsys = ""; foreach my $name (sort { ($data{$a}->{subsys} cmp $data{$b}->{subsys}) or - ($a cmp $b) + ("\L$a" cmp "\L$b") } keys %data) { if ($cur_subsys ne $data{$name}->{subsys}) { @@ -400,6 +432,17 @@ if ($cmd eq "current") { $arch =~s/\s+$//; } +if ($cmd eq "ls" or $cmd eq "list") { + if (!$arch) { + $arch = qx(uname -m | sed 's/x86_64/x86/' | sed 's/i386/x86/'); + $arch =~s/\s+$//; + } + + list_arch_features; + + exit; +} + if ($cmd ne "validate") { if ($arch) { output_arch_table; @@ -418,18 +461,26 @@ get_feat.pl - parse the Linux Feature files and produce a ReST book. =head1 SYNOPSIS -B [--debug] [--man] [--help] [--dir=] - [--arch=] [--feat=] [] +B [--debug] [--man] [--help] [--dir=] [--arch=] + [--feature=|--feat=] [] Where can be: =over 8 -B - output features for this machine's architecture +B - output table in ReST compatible ASCII format + with features for this machine's architecture + +B - output table(s) in ReST compatible ASCII format + with features in ReST markup language. The output + is affected by --arch or --feat/--feature flags. -B - output features in ReST markup language +B - validate the contents of the files under + Documentation/features. -B - validate the feature contents +B or B - list features for this machine's architecture, + using an easier to parse format. + The output is affected by --arch flag. =back @@ -442,9 +493,9 @@ B - validate the feature contents Output features for an specific architecture, optionally filtering for a single specific feature. -=item B<--feat> +=item B<--feat> or B<--feature> -Output features for a single specific architecture. +Output features for a single specific feature. =item B<--dir> -- cgit v1.2.3 From 7d2c6b1edf790d96e9017a0b27be2425e1af1532 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Dec 2020 09:17:32 +0100 Subject: scripts: kernel-doc: fix parsing function-like typedefs Changeset 6b80975c6308 ("scripts: kernel-doc: fix typedef parsing") added support for things like: typedef unsigned long foo(); However, it caused a regression on this prototype: typedef bool v4l2_check_dv_timings_fnc(const struct v4l2_dv_timings *t, void *handle); This is only noticed after adding a patch that checks if the kernel-doc identifier matches the typedef: ./scripts/kernel-doc -none $(git grep '^.. kernel-doc::' Documentation/ |cut -d ' ' -f 3|sort|uniq) 2>&1|grep expecting include/media/v4l2-dv-timings.h:38: warning: expecting prototype for typedef v4l2_check_dv_timings_fnc. Prototype was for typedef nc instead The problem is that, with the new parsing logic, it is not checking for complete words at the type part. Fix it by adding a \b at the end of each type word at the regex. fixes: 6b80975c6308 ("scripts: kernel-doc: fix typedef parsing") Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/218ff56dcb8e73755005d3fb64586eb1841a276b.1606896997.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet --- scripts/kernel-doc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 9b6ddeb097e9..6325bec3f66f 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1431,7 +1431,7 @@ sub dump_enum($$) { } } -my $typedef_type = qr { ((?:\s+[\w\*]+){1,8})\s* }x; +my $typedef_type = qr { ((?:\s+[\w\*]+\b){1,8})\s* }x; my $typedef_ident = qr { \*?\s*(\w\S+)\s* }x; my $typedef_args = qr { \s*\((.*)\); }x; -- cgit v1.2.3 From dbb9090232936c08510b7d028b8a6e03b4716154 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 4 Dec 2020 16:32:28 +0100 Subject: scripts: get_feat.pl: make complete table more coincise Currently, there are too many white spaces at the tables, and the information is very sparsed on it. Make the format a lot more compact. Suggested-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/8165ff379313e63a69898db19d790e4436224ffd.1607095090.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet --- scripts/get_feat.pl | 105 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 37 deletions(-) (limited to 'scripts') diff --git a/scripts/get_feat.pl b/scripts/get_feat.pl index 81d1b78d65c9..10bf23fbc9c5 100755 --- a/scripts/get_feat.pl +++ b/scripts/get_feat.pl @@ -325,10 +325,10 @@ sub output_feature { # Output all features for all architectures # -sub matrix_lines($$) { - my $partial = shift; +sub matrix_lines($$$) { + my $desc_size = shift; + my $status_size = shift; my $header = shift; - my $split; my $fill; my $ln_marker; @@ -338,24 +338,14 @@ sub matrix_lines($$) { $ln_marker = "-"; } - if ($partial) { - $split = "|"; - $fill = " "; - } else { - $split = "+"; - $fill = $ln_marker; - } + $fill = $ln_marker; - print $split; + print "+"; print $fill x $max_size_name; - print $split; - print $fill x $max_size_kconfig; - print $split; - print $fill x $max_size_description; print "+"; - print $ln_marker x $max_size_arch; + print $fill x $desc_size; print "+"; - print $ln_marker x $max_size_status; + print $ln_marker x $status_size; print "+\n"; } @@ -366,6 +356,14 @@ sub output_matrix { print "$title\n"; print "=" x length($title) . "\n\n"; + my $desc_title = "$h_kconfig / $h_description"; + + my $desc_size = $max_size_kconfig + 4; + $desc_size = $max_size_description if ($max_size_description > $desc_size); + $desc_size = length($desc_title) if (length($desc_title) > $desc_size); + + my $status_size = 60; + my $cur_subsys = ""; foreach my $name (sort { ($data{$a}->{subsys} cmp $data{$b}->{subsys}) or @@ -383,36 +381,69 @@ sub output_matrix { print "$title\n"; print "=" x length($title) . "\n\n"; - matrix_lines(0, 0); - printf "|%-${max_size_name}s", $h_name; - printf "|%-${max_size_kconfig}s", $h_kconfig; - printf "|%-${max_size_description}s", $h_description; - printf "|%-${max_size_arch}s", $h_arch; - printf "|%-${max_size_status}s|\n", $h_status; + matrix_lines($desc_size, $status_size, 0); + + printf "|%-${max_size_name}s", $h_name; + printf "|%-${desc_size}s", $desc_title; - matrix_lines(0, 1); + printf "|%-${status_size}s|\n", "Status per architecture"; + matrix_lines($desc_size, $status_size, 1); } my %arch_table = %{$data{$name}->{table}}; - my $first = 1; - foreach my $arch (sort keys %arch_table) { - if ($first) { - printf "|%-${max_size_name}s", $name; - printf "|%-${max_size_kconfig}s", $data{$name}->{kconfig}; - printf "|%-${max_size_description}s", $data{$name}->{description}; - $first = 0; + my $cur_status = ""; + + my @lines; + my $line = ""; + foreach my $arch (sort { + ($arch_table{$a} cmp $arch_table{$b}) or + ("\L$a" cmp "\L$b") + } keys %arch_table) { + + my $status = $arch_table{$arch}; + + if ($status eq "---") { + $status = "Not compatible"; + } + + if ($status ne $cur_status) { + if ($line ne "") { + push @lines, $line; + $line = ""; + } + $line = "- **" . $status . "**: " . $arch; + } elsif (length($line) + length ($arch) + 2 < $status_size) { + $line .= ", " . $arch; } else { - matrix_lines(1, 0); + push @lines, $line; + $line = " " . $arch; + } + $cur_status = $status; + } + push @lines, $line if ($line ne ""); + + # Ensure that description will be printed + push @lines, "" while (scalar(@lines) < 2); + my $ln = 0; + for my $line(@lines) { + if (!$ln) { + printf "|%-${max_size_name}s", $name; + printf "|%-${desc_size}s", "``" . $data{$name}->{kconfig} . "``"; + } elsif ($ln == 2) { + printf "|%-${max_size_name}s", ""; + printf "|%-${desc_size}s", $data{$name}->{description}; + } else { printf "|%-${max_size_name}s", ""; - printf "|%-${max_size_kconfig}s", ""; - printf "|%-${max_size_description}s", ""; + printf "|%-${desc_size}s", ""; } - printf "|%-${max_size_arch}s", $arch; - printf "|%-${max_size_status}s|\n", $arch_table{$arch}; + + printf "|%-${status_size}s|\n", $line; + + $ln++; } - matrix_lines(0, 0); + matrix_lines($desc_size, $status_size, 0); } } -- cgit v1.2.3 From 4fa32f8702891713fcd8ae807da4bab862812c94 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 4 Dec 2020 16:32:29 +0100 Subject: scripts: get_feat.pl: change the group by order Right now, arch compatibility is grouped by status at the alphabetical order from A to Z, and then from a to z, e. g:. --- TODO ok Revert the order, in order to print first the OK results, then TODO, and, finally, the not compatible ones. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/46d53d138eab8e4a55124323ceb5b212c6eedd08.1607095090.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet --- scripts/get_feat.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/get_feat.pl b/scripts/get_feat.pl index 10bf23fbc9c5..3f73c8534059 100755 --- a/scripts/get_feat.pl +++ b/scripts/get_feat.pl @@ -397,7 +397,7 @@ sub output_matrix { my @lines; my $line = ""; foreach my $arch (sort { - ($arch_table{$a} cmp $arch_table{$b}) or + ($arch_table{$b} cmp $arch_table{$a}) or ("\L$a" cmp "\L$b") } keys %arch_table) { -- cgit v1.2.3 From f5889e70b9ccd25f1f140c372eaa7ded9819c102 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 4 Dec 2020 16:32:30 +0100 Subject: scripts: get_feat.pl: reduce table width for all features output Auto-adjust the table columns width to better fit under terminals, by breaking the description on multiple lines and auto-estimating the minimal size for the per-architecture status. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/9d39ac3fd51f1360aecc328c01558be88a1d6930.1607095090.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet --- scripts/get_feat.pl | 71 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 12 deletions(-) (limited to 'scripts') diff --git a/scripts/get_feat.pl b/scripts/get_feat.pl index 3f73c8534059..457712355676 100755 --- a/scripts/get_feat.pl +++ b/scripts/get_feat.pl @@ -19,6 +19,11 @@ $basename =~ s,/[^/]+$,/,; my $prefix=$basename . "../Documentation/features"; +# Used only at for full features output. The script will auto-adjust +# such values for the minimal possible values +my $status_size = 1; +my $description_size = 1; + GetOptions( "debug|d+" => \$debug, "dir=s" => \$prefix, @@ -77,7 +82,10 @@ my $max_size_kconfig = length($h_kconfig); my $max_size_description = length($h_description); my $max_size_subsys = length($h_subsys); my $max_size_status = length($h_status); -my $max_size_arch = length($h_arch); + +my $max_size_arch = 0; +my $max_size_arch_with_header; +my $max_description_word = 0; sub parse_feat { my $file = $File::Find::name; @@ -127,6 +135,13 @@ sub parse_feat { if (length($description) > $max_size_description) { $max_size_description = length($description); } + + foreach my $word (split /\s+/, $description) { + if (length($word) > $max_description_word) { + $max_description_word = length($word); + } + } + next; } next if (m/^\\s*$/); @@ -180,6 +195,8 @@ sub parse_feat { $data{$name}->{description} = $description; $data{$name}->{comments} = $comments; $data{$name}->{table} = \%arch_table; + + $max_size_arch_with_header = $max_size_arch + length($h_arch); } # @@ -296,7 +313,7 @@ sub output_feature { print "$com\n\n"; } - print "=" x $max_size_arch; + print "=" x $max_size_arch_with_header; print " "; print "=" x $max_size_status; print "\n"; @@ -304,7 +321,7 @@ sub output_feature { printf "%-${max_size_arch}s ", $h_arch; printf "%-${max_size_status}s", $h_status . "\n"; - print "=" x $max_size_arch; + print "=" x $max_size_arch_with_header; print " "; print "=" x $max_size_status; print "\n"; @@ -315,7 +332,7 @@ sub output_feature { printf "%-${max_size_status}s\n", $arch_table{$arch}; } - print "=" x $max_size_arch; + print "=" x $max_size_arch_with_header; print " "; print "=" x $max_size_status; print "\n"; @@ -351,6 +368,7 @@ sub matrix_lines($$$) { sub output_matrix { my $title = "Feature status on all architectures"; + my $notcompat = "Not compatible"; print "=" x length($title) . "\n"; print "$title\n"; @@ -359,10 +377,21 @@ sub output_matrix { my $desc_title = "$h_kconfig / $h_description"; my $desc_size = $max_size_kconfig + 4; - $desc_size = $max_size_description if ($max_size_description > $desc_size); + if (!$description_size) { + $desc_size = $max_size_description if ($max_size_description > $desc_size); + } else { + $desc_size = $description_size if ($description_size > $desc_size); + } + $desc_size = $max_description_word if ($max_description_word > $desc_size); + $desc_size = length($desc_title) if (length($desc_title) > $desc_size); - my $status_size = 60; + $max_size_status = length($notcompat) if (length($notcompat) > $max_size_status); + + # Ensure that the status will fit + my $min_status_size = $max_size_status + $max_size_arch + 6; + $status_size = $min_status_size if ($status_size < $min_status_size); + my $cur_subsys = ""; foreach my $name (sort { @@ -394,7 +423,7 @@ sub output_matrix { my %arch_table = %{$data{$name}->{table}}; my $cur_status = ""; - my @lines; + my (@lines, @descs); my $line = ""; foreach my $arch (sort { ($arch_table{$b} cmp $arch_table{$a}) or @@ -404,7 +433,7 @@ sub output_matrix { my $status = $arch_table{$arch}; if ($status eq "---") { - $status = "Not compatible"; + $status = $notcompat; } if ($status ne $cur_status) { @@ -423,17 +452,35 @@ sub output_matrix { } push @lines, $line if ($line ne ""); - # Ensure that description will be printed - push @lines, "" while (scalar(@lines) < 2); + my $description = $data{$name}->{description}; + while (length($description) > $desc_size) { + my $d = substr $description, 0, $desc_size; + + # Ensure that it will end on a space + # if it can't, it means that the size is too small + # Instead of aborting it, let's print what we have + if (!($d =~ s/^(.*)\s+.*/$1/)) { + $d = substr $d, 0, -1; + push @descs, "$d\\"; + $description =~ s/^\Q$d\E//; + } else { + push @descs, $d; + $description =~ s/^\Q$d\E\s+//; + } + } + push @descs, $description; + + # Ensure that the full description will be printed + push @lines, "" while (scalar(@lines) < 2 + scalar(@descs)); my $ln = 0; for my $line(@lines) { if (!$ln) { printf "|%-${max_size_name}s", $name; printf "|%-${desc_size}s", "``" . $data{$name}->{kconfig} . "``"; - } elsif ($ln == 2) { + } elsif ($ln >= 2 && scalar(@descs)) { printf "|%-${max_size_name}s", ""; - printf "|%-${desc_size}s", $data{$name}->{description}; + printf "|%-${desc_size}s", shift @descs; } else { printf "|%-${max_size_name}s", ""; printf "|%-${desc_size}s", ""; -- cgit v1.2.3