xref: /openbmc/linux/scripts/get_feat.pl (revision 2bc64308)
1*2bc64308SDavid Reaver#!/usr/bin/env perl
252a4be3fSMauro Carvalho Chehab# SPDX-License-Identifier: GPL-2.0
352a4be3fSMauro Carvalho Chehab
452a4be3fSMauro Carvalho Chehabuse strict;
552a4be3fSMauro Carvalho Chehabuse Pod::Usage;
652a4be3fSMauro Carvalho Chehabuse Getopt::Long;
752a4be3fSMauro Carvalho Chehabuse File::Find;
852a4be3fSMauro Carvalho Chehabuse Fcntl ':mode';
9ca908577SMauro Carvalho Chehabuse Cwd 'abs_path';
1052a4be3fSMauro Carvalho Chehab
1152a4be3fSMauro Carvalho Chehabmy $help;
1252a4be3fSMauro Carvalho Chehabmy $man;
1352a4be3fSMauro Carvalho Chehabmy $debug;
1452a4be3fSMauro Carvalho Chehabmy $arch;
1552a4be3fSMauro Carvalho Chehabmy $feat;
1601096e5cSMauro Carvalho Chehabmy $enable_fname;
17ca908577SMauro Carvalho Chehab
18ca908577SMauro Carvalho Chehabmy $basename = abs_path($0);
19ca908577SMauro Carvalho Chehab$basename =~ s,/[^/]+$,/,;
20ca908577SMauro Carvalho Chehab
21ca908577SMauro Carvalho Chehabmy $prefix=$basename . "../Documentation/features";
2252a4be3fSMauro Carvalho Chehab
23f5889e70SMauro Carvalho Chehab# Used only at for full features output. The script will auto-adjust
24f5889e70SMauro Carvalho Chehab# such values for the minimal possible values
25f5889e70SMauro Carvalho Chehabmy $status_size = 1;
26f5889e70SMauro Carvalho Chehabmy $description_size = 1;
27f5889e70SMauro Carvalho Chehab
2852a4be3fSMauro Carvalho ChehabGetOptions(
2952a4be3fSMauro Carvalho Chehab	"debug|d+" => \$debug,
3052a4be3fSMauro Carvalho Chehab	"dir=s" => \$prefix,
3152a4be3fSMauro Carvalho Chehab	'help|?' => \$help,
3252a4be3fSMauro Carvalho Chehab	'arch=s' => \$arch,
3352a4be3fSMauro Carvalho Chehab	'feat=s' => \$feat,
34ca908577SMauro Carvalho Chehab	'feature=s' => \$feat,
3501096e5cSMauro Carvalho Chehab	"enable-fname" => \$enable_fname,
3652a4be3fSMauro Carvalho Chehab	man => \$man
3752a4be3fSMauro Carvalho Chehab) or pod2usage(2);
3852a4be3fSMauro Carvalho Chehab
3952a4be3fSMauro Carvalho Chehabpod2usage(1) if $help;
4052a4be3fSMauro Carvalho Chehabpod2usage(-exitstatus => 0, -verbose => 2) if $man;
4152a4be3fSMauro Carvalho Chehab
42ca908577SMauro Carvalho Chehabpod2usage(1) if (scalar @ARGV < 1 || @ARGV > 2);
4352a4be3fSMauro Carvalho Chehab
4452a4be3fSMauro Carvalho Chehabmy ($cmd, $arg) = @ARGV;
4552a4be3fSMauro Carvalho Chehab
46ca908577SMauro Carvalho Chehabpod2usage(2) if ($cmd ne "current" && $cmd ne "rest" && $cmd ne "validate"
47ca908577SMauro Carvalho Chehab		&& $cmd ne "ls" && $cmd ne "list");
4852a4be3fSMauro Carvalho Chehab
4952a4be3fSMauro Carvalho Chehabrequire Data::Dumper if ($debug);
5052a4be3fSMauro Carvalho Chehab
5152a4be3fSMauro Carvalho Chehabmy %data;
5252a4be3fSMauro Carvalho Chehabmy %archs;
5352a4be3fSMauro Carvalho Chehab
5452a4be3fSMauro Carvalho Chehab#
5552a4be3fSMauro Carvalho Chehab# Displays an error message, printing file name and line
5652a4be3fSMauro Carvalho Chehab#
5752a4be3fSMauro Carvalho Chehabsub parse_error($$$$) {
5852a4be3fSMauro Carvalho Chehab	my ($file, $ln, $msg, $data) = @_;
5952a4be3fSMauro Carvalho Chehab
6052a4be3fSMauro Carvalho Chehab	$data =~ s/\s+$/\n/;
6152a4be3fSMauro Carvalho Chehab
6252a4be3fSMauro Carvalho Chehab	print STDERR "Warning: file $file#$ln:\n\t$msg";
6352a4be3fSMauro Carvalho Chehab
6452a4be3fSMauro Carvalho Chehab	if ($data ne "") {
6552a4be3fSMauro Carvalho Chehab		print STDERR ". Line\n\t\t$data";
6652a4be3fSMauro Carvalho Chehab	} else {
6752a4be3fSMauro Carvalho Chehab	    print STDERR "\n";
6852a4be3fSMauro Carvalho Chehab	}
6952a4be3fSMauro Carvalho Chehab}
7052a4be3fSMauro Carvalho Chehab
7152a4be3fSMauro Carvalho Chehab#
7252a4be3fSMauro Carvalho Chehab# Parse a features file, storing its contents at %data
7352a4be3fSMauro Carvalho Chehab#
7452a4be3fSMauro Carvalho Chehab
7552a4be3fSMauro Carvalho Chehabmy $h_name = "Feature";
7652a4be3fSMauro Carvalho Chehabmy $h_kconfig = "Kconfig";
7752a4be3fSMauro Carvalho Chehabmy $h_description = "Description";
7852a4be3fSMauro Carvalho Chehabmy $h_subsys = "Subsystem";
7952a4be3fSMauro Carvalho Chehabmy $h_status = "Status";
8052a4be3fSMauro Carvalho Chehabmy $h_arch = "Architecture";
8152a4be3fSMauro Carvalho Chehab
8252a4be3fSMauro Carvalho Chehabmy $max_size_name = length($h_name);
8352a4be3fSMauro Carvalho Chehabmy $max_size_kconfig = length($h_kconfig);
8452a4be3fSMauro Carvalho Chehabmy $max_size_description = length($h_description);
8552a4be3fSMauro Carvalho Chehabmy $max_size_subsys = length($h_subsys);
8652a4be3fSMauro Carvalho Chehabmy $max_size_status = length($h_status);
87f5889e70SMauro Carvalho Chehab
88f5889e70SMauro Carvalho Chehabmy $max_size_arch = 0;
89f5889e70SMauro Carvalho Chehabmy $max_size_arch_with_header;
90f5889e70SMauro Carvalho Chehabmy $max_description_word = 0;
9152a4be3fSMauro Carvalho Chehab
9252a4be3fSMauro Carvalho Chehabsub parse_feat {
9352a4be3fSMauro Carvalho Chehab	my $file = $File::Find::name;
9452a4be3fSMauro Carvalho Chehab
9552a4be3fSMauro Carvalho Chehab	my $mode = (stat($file))[2];
9652a4be3fSMauro Carvalho Chehab	return if ($mode & S_IFDIR);
9752a4be3fSMauro Carvalho Chehab	return if ($file =~ m,($prefix)/arch-support.txt,);
9852a4be3fSMauro Carvalho Chehab	return if (!($file =~ m,arch-support.txt$,));
9952a4be3fSMauro Carvalho Chehab
10001096e5cSMauro Carvalho Chehab	if ($enable_fname) {
10101096e5cSMauro Carvalho Chehab		printf ".. FILE %s\n", abs_path($file);
10201096e5cSMauro Carvalho Chehab	}
10301096e5cSMauro Carvalho Chehab
10452a4be3fSMauro Carvalho Chehab	my $subsys = "";
10552a4be3fSMauro Carvalho Chehab	$subsys = $2 if ( m,.*($prefix)/([^/]+).*,);
10652a4be3fSMauro Carvalho Chehab
10752a4be3fSMauro Carvalho Chehab	if (length($subsys) > $max_size_subsys) {
10852a4be3fSMauro Carvalho Chehab		$max_size_subsys = length($subsys);
10952a4be3fSMauro Carvalho Chehab	}
11052a4be3fSMauro Carvalho Chehab
11152a4be3fSMauro Carvalho Chehab	my $name;
11252a4be3fSMauro Carvalho Chehab	my $kconfig;
11352a4be3fSMauro Carvalho Chehab	my $description;
11452a4be3fSMauro Carvalho Chehab	my $comments = "";
11552a4be3fSMauro Carvalho Chehab	my $last_status;
11652a4be3fSMauro Carvalho Chehab	my $ln;
11752a4be3fSMauro Carvalho Chehab	my %arch_table;
11852a4be3fSMauro Carvalho Chehab
11952a4be3fSMauro Carvalho Chehab	print STDERR "Opening $file\n" if ($debug > 1);
12052a4be3fSMauro Carvalho Chehab	open IN, $file;
12152a4be3fSMauro Carvalho Chehab
12252a4be3fSMauro Carvalho Chehab	while(<IN>) {
12352a4be3fSMauro Carvalho Chehab		$ln++;
12452a4be3fSMauro Carvalho Chehab
12552a4be3fSMauro Carvalho Chehab		if (m/^\#\s+Feature\s+name:\s*(.*\S)/) {
12652a4be3fSMauro Carvalho Chehab			$name = $1;
12752a4be3fSMauro Carvalho Chehab			if (length($name) > $max_size_name) {
12852a4be3fSMauro Carvalho Chehab				$max_size_name = length($name);
12952a4be3fSMauro Carvalho Chehab			}
13052a4be3fSMauro Carvalho Chehab			next;
13152a4be3fSMauro Carvalho Chehab		}
13252a4be3fSMauro Carvalho Chehab		if (m/^\#\s+Kconfig:\s*(.*\S)/) {
13352a4be3fSMauro Carvalho Chehab			$kconfig = $1;
13452a4be3fSMauro Carvalho Chehab			if (length($kconfig) > $max_size_kconfig) {
13552a4be3fSMauro Carvalho Chehab				$max_size_kconfig = length($kconfig);
13652a4be3fSMauro Carvalho Chehab			}
13752a4be3fSMauro Carvalho Chehab			next;
13852a4be3fSMauro Carvalho Chehab		}
13952a4be3fSMauro Carvalho Chehab		if (m/^\#\s+description:\s*(.*\S)/) {
14052a4be3fSMauro Carvalho Chehab			$description = $1;
14152a4be3fSMauro Carvalho Chehab			if (length($description) > $max_size_description) {
14252a4be3fSMauro Carvalho Chehab				$max_size_description = length($description);
14352a4be3fSMauro Carvalho Chehab			}
144f5889e70SMauro Carvalho Chehab
145f5889e70SMauro Carvalho Chehab			foreach my $word (split /\s+/, $description) {
146f5889e70SMauro Carvalho Chehab				if (length($word) > $max_description_word) {
147f5889e70SMauro Carvalho Chehab					$max_description_word = length($word);
148f5889e70SMauro Carvalho Chehab				}
149f5889e70SMauro Carvalho Chehab			}
150f5889e70SMauro Carvalho Chehab
15152a4be3fSMauro Carvalho Chehab			next;
15252a4be3fSMauro Carvalho Chehab		}
15352a4be3fSMauro Carvalho Chehab		next if (m/^\\s*$/);
15452a4be3fSMauro Carvalho Chehab		next if (m/^\s*\-+\s*$/);
15552a4be3fSMauro Carvalho Chehab		next if (m/^\s*\|\s*arch\s*\|\s*status\s*\|\s*$/);
15652a4be3fSMauro Carvalho Chehab
15752a4be3fSMauro Carvalho Chehab		if (m/^\#\s*(.*)/) {
15852a4be3fSMauro Carvalho Chehab			$comments .= "$1\n";
15952a4be3fSMauro Carvalho Chehab			next;
16052a4be3fSMauro Carvalho Chehab		}
16152a4be3fSMauro Carvalho Chehab		if (m/^\s*\|\s*(\S+):\s*\|\s*(\S+)\s*\|\s*$/) {
16252a4be3fSMauro Carvalho Chehab			my $a = $1;
16352a4be3fSMauro Carvalho Chehab			my $status = $2;
16452a4be3fSMauro Carvalho Chehab
16552a4be3fSMauro Carvalho Chehab			if (length($status) > $max_size_status) {
16652a4be3fSMauro Carvalho Chehab				$max_size_status = length($status);
16752a4be3fSMauro Carvalho Chehab			}
16852a4be3fSMauro Carvalho Chehab			if (length($a) > $max_size_arch) {
16952a4be3fSMauro Carvalho Chehab				$max_size_arch = length($a);
17052a4be3fSMauro Carvalho Chehab			}
17152a4be3fSMauro Carvalho Chehab
17252a4be3fSMauro Carvalho Chehab			$status = "---" if ($status =~ m/^\.\.$/);
17352a4be3fSMauro Carvalho Chehab
17452a4be3fSMauro Carvalho Chehab			$archs{$a} = 1;
17552a4be3fSMauro Carvalho Chehab			$arch_table{$a} = $status;
17652a4be3fSMauro Carvalho Chehab			next;
17752a4be3fSMauro Carvalho Chehab		}
17852a4be3fSMauro Carvalho Chehab
17952a4be3fSMauro Carvalho Chehab		#Everything else is an error
18052a4be3fSMauro Carvalho Chehab		parse_error($file, $ln, "line is invalid", $_);
18152a4be3fSMauro Carvalho Chehab	}
18252a4be3fSMauro Carvalho Chehab	close IN;
18352a4be3fSMauro Carvalho Chehab
18452a4be3fSMauro Carvalho Chehab	if (!$name) {
18552a4be3fSMauro Carvalho Chehab		parse_error($file, $ln, "Feature name not found", "");
18652a4be3fSMauro Carvalho Chehab		return;
18752a4be3fSMauro Carvalho Chehab	}
18852a4be3fSMauro Carvalho Chehab
18952a4be3fSMauro Carvalho Chehab	parse_error($file, $ln, "Subsystem not found", "") if (!$subsys);
19052a4be3fSMauro Carvalho Chehab	parse_error($file, $ln, "Kconfig not found", "") if (!$kconfig);
19152a4be3fSMauro Carvalho Chehab	parse_error($file, $ln, "Description not found", "") if (!$description);
19252a4be3fSMauro Carvalho Chehab
19352a4be3fSMauro Carvalho Chehab	if (!%arch_table) {
19452a4be3fSMauro Carvalho Chehab		parse_error($file, $ln, "Architecture table not found", "");
19552a4be3fSMauro Carvalho Chehab		return;
19652a4be3fSMauro Carvalho Chehab	}
19752a4be3fSMauro Carvalho Chehab
19852a4be3fSMauro Carvalho Chehab	$data{$name}->{where} = $file;
19952a4be3fSMauro Carvalho Chehab	$data{$name}->{subsys} = $subsys;
20052a4be3fSMauro Carvalho Chehab	$data{$name}->{kconfig} = $kconfig;
20152a4be3fSMauro Carvalho Chehab	$data{$name}->{description} = $description;
20252a4be3fSMauro Carvalho Chehab	$data{$name}->{comments} = $comments;
20352a4be3fSMauro Carvalho Chehab	$data{$name}->{table} = \%arch_table;
204f5889e70SMauro Carvalho Chehab
205f5889e70SMauro Carvalho Chehab	$max_size_arch_with_header = $max_size_arch + length($h_arch);
20652a4be3fSMauro Carvalho Chehab}
20752a4be3fSMauro Carvalho Chehab
20852a4be3fSMauro Carvalho Chehab#
20952a4be3fSMauro Carvalho Chehab# Output feature(s) for a given architecture
21052a4be3fSMauro Carvalho Chehab#
21152a4be3fSMauro Carvalho Chehabsub output_arch_table {
21252a4be3fSMauro Carvalho Chehab	my $title = "Feature status on $arch architecture";
21352a4be3fSMauro Carvalho Chehab
21452a4be3fSMauro Carvalho Chehab	print "=" x length($title) . "\n";
21552a4be3fSMauro Carvalho Chehab	print "$title\n";
21652a4be3fSMauro Carvalho Chehab	print "=" x length($title) . "\n\n";
21752a4be3fSMauro Carvalho Chehab
21852a4be3fSMauro Carvalho Chehab	print "=" x $max_size_subsys;
21952a4be3fSMauro Carvalho Chehab	print "  ";
22052a4be3fSMauro Carvalho Chehab	print "=" x $max_size_name;
22152a4be3fSMauro Carvalho Chehab	print "  ";
22252a4be3fSMauro Carvalho Chehab	print "=" x $max_size_kconfig;
22352a4be3fSMauro Carvalho Chehab	print "  ";
22452a4be3fSMauro Carvalho Chehab	print "=" x $max_size_status;
22552a4be3fSMauro Carvalho Chehab	print "  ";
22652a4be3fSMauro Carvalho Chehab	print "=" x $max_size_description;
22752a4be3fSMauro Carvalho Chehab	print "\n";
22852a4be3fSMauro Carvalho Chehab	printf "%-${max_size_subsys}s  ", $h_subsys;
22952a4be3fSMauro Carvalho Chehab	printf "%-${max_size_name}s  ", $h_name;
23052a4be3fSMauro Carvalho Chehab	printf "%-${max_size_kconfig}s  ", $h_kconfig;
23152a4be3fSMauro Carvalho Chehab	printf "%-${max_size_status}s  ", $h_status;
23252a4be3fSMauro Carvalho Chehab	printf "%-${max_size_description}s\n", $h_description;
23352a4be3fSMauro Carvalho Chehab	print "=" x $max_size_subsys;
23452a4be3fSMauro Carvalho Chehab	print "  ";
23552a4be3fSMauro Carvalho Chehab	print "=" x $max_size_name;
23652a4be3fSMauro Carvalho Chehab	print "  ";
23752a4be3fSMauro Carvalho Chehab	print "=" x $max_size_kconfig;
23852a4be3fSMauro Carvalho Chehab	print "  ";
23952a4be3fSMauro Carvalho Chehab	print "=" x $max_size_status;
24052a4be3fSMauro Carvalho Chehab	print "  ";
24152a4be3fSMauro Carvalho Chehab	print "=" x $max_size_description;
24252a4be3fSMauro Carvalho Chehab	print "\n";
24352a4be3fSMauro Carvalho Chehab
24452a4be3fSMauro Carvalho Chehab	foreach my $name (sort {
24552a4be3fSMauro Carvalho Chehab				($data{$a}->{subsys} cmp $data{$b}->{subsys}) ||
246ca908577SMauro Carvalho Chehab				("\L$a" cmp "\L$b")
24752a4be3fSMauro Carvalho Chehab			       } keys %data) {
24852a4be3fSMauro Carvalho Chehab		next if ($feat && $name ne $feat);
24952a4be3fSMauro Carvalho Chehab
25052a4be3fSMauro Carvalho Chehab		my %arch_table = %{$data{$name}->{table}};
25152a4be3fSMauro Carvalho Chehab		printf "%-${max_size_subsys}s  ", $data{$name}->{subsys};
25252a4be3fSMauro Carvalho Chehab		printf "%-${max_size_name}s  ", $name;
25352a4be3fSMauro Carvalho Chehab		printf "%-${max_size_kconfig}s  ", $data{$name}->{kconfig};
25452a4be3fSMauro Carvalho Chehab		printf "%-${max_size_status}s  ", $arch_table{$arch};
255ca908577SMauro Carvalho Chehab		printf "%-s\n", $data{$name}->{description};
25652a4be3fSMauro Carvalho Chehab	}
25752a4be3fSMauro Carvalho Chehab
25852a4be3fSMauro Carvalho Chehab	print "=" x $max_size_subsys;
25952a4be3fSMauro Carvalho Chehab	print "  ";
26052a4be3fSMauro Carvalho Chehab	print "=" x $max_size_name;
26152a4be3fSMauro Carvalho Chehab	print "  ";
26252a4be3fSMauro Carvalho Chehab	print "=" x $max_size_kconfig;
26352a4be3fSMauro Carvalho Chehab	print "  ";
26452a4be3fSMauro Carvalho Chehab	print "=" x $max_size_status;
26552a4be3fSMauro Carvalho Chehab	print "  ";
26652a4be3fSMauro Carvalho Chehab	print "=" x $max_size_description;
26752a4be3fSMauro Carvalho Chehab	print "\n";
26852a4be3fSMauro Carvalho Chehab}
26952a4be3fSMauro Carvalho Chehab
27052a4be3fSMauro Carvalho Chehab#
271ca908577SMauro Carvalho Chehab# list feature(s) for a given architecture
272ca908577SMauro Carvalho Chehab#
273ca908577SMauro Carvalho Chehabsub list_arch_features {
274ca908577SMauro Carvalho Chehab	print "#\n# Kernel feature support matrix of the '$arch' architecture:\n#\n";
275ca908577SMauro Carvalho Chehab
276ca908577SMauro Carvalho Chehab	foreach my $name (sort {
277ca908577SMauro Carvalho Chehab				($data{$a}->{subsys} cmp $data{$b}->{subsys}) ||
278ca908577SMauro Carvalho Chehab				("\L$a" cmp "\L$b")
279ca908577SMauro Carvalho Chehab			       } keys %data) {
280ca908577SMauro Carvalho Chehab		next if ($feat && $name ne $feat);
281ca908577SMauro Carvalho Chehab
282ca908577SMauro Carvalho Chehab		my %arch_table = %{$data{$name}->{table}};
283ca908577SMauro Carvalho Chehab
284ca908577SMauro Carvalho Chehab		my $status = $arch_table{$arch};
285ca908577SMauro Carvalho Chehab		$status = " " x ((4 - length($status)) / 2) . $status;
286ca908577SMauro Carvalho Chehab
287ca908577SMauro Carvalho Chehab		printf " %${max_size_subsys}s/ ", $data{$name}->{subsys};
288ca908577SMauro Carvalho Chehab		printf "%-${max_size_name}s: ", $name;
289ca908577SMauro Carvalho Chehab		printf "%-5s|   ", $status;
290ca908577SMauro Carvalho Chehab		printf "%${max_size_kconfig}s # ", $data{$name}->{kconfig};
291ca908577SMauro Carvalho Chehab		printf " %s\n", $data{$name}->{description};
292ca908577SMauro Carvalho Chehab	}
293ca908577SMauro Carvalho Chehab}
294ca908577SMauro Carvalho Chehab
295ca908577SMauro Carvalho Chehab#
29652a4be3fSMauro Carvalho Chehab# Output a feature on all architectures
29752a4be3fSMauro Carvalho Chehab#
29852a4be3fSMauro Carvalho Chehabsub output_feature {
29952a4be3fSMauro Carvalho Chehab	my $title = "Feature $feat";
30052a4be3fSMauro Carvalho Chehab
30152a4be3fSMauro Carvalho Chehab	print "=" x length($title) . "\n";
30252a4be3fSMauro Carvalho Chehab	print "$title\n";
30352a4be3fSMauro Carvalho Chehab	print "=" x length($title) . "\n\n";
30452a4be3fSMauro Carvalho Chehab
30552a4be3fSMauro Carvalho Chehab	print ":Subsystem: $data{$feat}->{subsys} \n" if ($data{$feat}->{subsys});
30652a4be3fSMauro Carvalho Chehab	print ":Kconfig: $data{$feat}->{kconfig} \n" if ($data{$feat}->{kconfig});
30752a4be3fSMauro Carvalho Chehab
30852a4be3fSMauro Carvalho Chehab	my $desc = $data{$feat}->{description};
30952a4be3fSMauro Carvalho Chehab	$desc =~ s/^([a-z])/\U$1/;
31052a4be3fSMauro Carvalho Chehab	$desc =~ s/\.?\s*//;
31152a4be3fSMauro Carvalho Chehab	print "\n$desc.\n\n";
31252a4be3fSMauro Carvalho Chehab
31352a4be3fSMauro Carvalho Chehab	my $com = $data{$feat}->{comments};
31452a4be3fSMauro Carvalho Chehab	$com =~ s/^\s+//;
31552a4be3fSMauro Carvalho Chehab	$com =~ s/\s+$//;
31652a4be3fSMauro Carvalho Chehab	if ($com) {
31752a4be3fSMauro Carvalho Chehab		print "Comments\n";
31852a4be3fSMauro Carvalho Chehab		print "--------\n\n";
31952a4be3fSMauro Carvalho Chehab		print "$com\n\n";
32052a4be3fSMauro Carvalho Chehab	}
32152a4be3fSMauro Carvalho Chehab
322f5889e70SMauro Carvalho Chehab	print "=" x $max_size_arch_with_header;
32352a4be3fSMauro Carvalho Chehab	print "  ";
32452a4be3fSMauro Carvalho Chehab	print "=" x $max_size_status;
32552a4be3fSMauro Carvalho Chehab	print "\n";
32652a4be3fSMauro Carvalho Chehab
32752a4be3fSMauro Carvalho Chehab	printf "%-${max_size_arch}s  ", $h_arch;
32852a4be3fSMauro Carvalho Chehab	printf "%-${max_size_status}s", $h_status . "\n";
32952a4be3fSMauro Carvalho Chehab
330f5889e70SMauro Carvalho Chehab	print "=" x $max_size_arch_with_header;
33152a4be3fSMauro Carvalho Chehab	print "  ";
33252a4be3fSMauro Carvalho Chehab	print "=" x $max_size_status;
33352a4be3fSMauro Carvalho Chehab	print "\n";
33452a4be3fSMauro Carvalho Chehab
33552a4be3fSMauro Carvalho Chehab	my %arch_table = %{$data{$feat}->{table}};
33652a4be3fSMauro Carvalho Chehab	foreach my $arch (sort keys %arch_table) {
33752a4be3fSMauro Carvalho Chehab		printf "%-${max_size_arch}s  ", $arch;
33852a4be3fSMauro Carvalho Chehab		printf "%-${max_size_status}s\n", $arch_table{$arch};
33952a4be3fSMauro Carvalho Chehab	}
34052a4be3fSMauro Carvalho Chehab
341f5889e70SMauro Carvalho Chehab	print "=" x $max_size_arch_with_header;
34252a4be3fSMauro Carvalho Chehab	print "  ";
34352a4be3fSMauro Carvalho Chehab	print "=" x $max_size_status;
34452a4be3fSMauro Carvalho Chehab	print "\n";
34552a4be3fSMauro Carvalho Chehab}
34652a4be3fSMauro Carvalho Chehab
34752a4be3fSMauro Carvalho Chehab#
34852a4be3fSMauro Carvalho Chehab# Output all features for all architectures
34952a4be3fSMauro Carvalho Chehab#
35052a4be3fSMauro Carvalho Chehab
351dbb90902SMauro Carvalho Chehabsub matrix_lines($$$) {
352dbb90902SMauro Carvalho Chehab	my $desc_size = shift;
353dbb90902SMauro Carvalho Chehab	my $status_size = shift;
354ba813f7cSMauro Carvalho Chehab	my $header = shift;
355ba813f7cSMauro Carvalho Chehab	my $fill;
356ba813f7cSMauro Carvalho Chehab	my $ln_marker;
35752a4be3fSMauro Carvalho Chehab
358ba813f7cSMauro Carvalho Chehab	if ($header) {
359ba813f7cSMauro Carvalho Chehab		$ln_marker = "=";
360ba813f7cSMauro Carvalho Chehab	} else {
361ba813f7cSMauro Carvalho Chehab		$ln_marker = "-";
36252a4be3fSMauro Carvalho Chehab	}
363ba813f7cSMauro Carvalho Chehab
364ba813f7cSMauro Carvalho Chehab	$fill = $ln_marker;
365ba813f7cSMauro Carvalho Chehab
366dbb90902SMauro Carvalho Chehab	print "+";
367ba813f7cSMauro Carvalho Chehab	print $fill x $max_size_name;
368ba813f7cSMauro Carvalho Chehab	print "+";
369dbb90902SMauro Carvalho Chehab	print $fill x $desc_size;
370ba813f7cSMauro Carvalho Chehab	print "+";
371dbb90902SMauro Carvalho Chehab	print $ln_marker x $status_size;
372ba813f7cSMauro Carvalho Chehab	print "+\n";
37352a4be3fSMauro Carvalho Chehab}
37452a4be3fSMauro Carvalho Chehab
37552a4be3fSMauro Carvalho Chehabsub output_matrix {
376ba813f7cSMauro Carvalho Chehab	my $title = "Feature status on all architectures";
377f5889e70SMauro Carvalho Chehab	my $notcompat = "Not compatible";
37852a4be3fSMauro Carvalho Chehab
37952a4be3fSMauro Carvalho Chehab	print "=" x length($title) . "\n";
38052a4be3fSMauro Carvalho Chehab	print "$title\n";
38152a4be3fSMauro Carvalho Chehab	print "=" x length($title) . "\n\n";
38252a4be3fSMauro Carvalho Chehab
383dbb90902SMauro Carvalho Chehab	my $desc_title = "$h_kconfig / $h_description";
384dbb90902SMauro Carvalho Chehab
385dbb90902SMauro Carvalho Chehab	my $desc_size = $max_size_kconfig + 4;
386f5889e70SMauro Carvalho Chehab	if (!$description_size) {
387dbb90902SMauro Carvalho Chehab		$desc_size = $max_size_description if ($max_size_description > $desc_size);
388f5889e70SMauro Carvalho Chehab	} else {
389f5889e70SMauro Carvalho Chehab		$desc_size = $description_size if ($description_size > $desc_size);
390f5889e70SMauro Carvalho Chehab	}
391f5889e70SMauro Carvalho Chehab	$desc_size = $max_description_word if ($max_description_word > $desc_size);
392f5889e70SMauro Carvalho Chehab
393dbb90902SMauro Carvalho Chehab	$desc_size = length($desc_title) if (length($desc_title) > $desc_size);
394dbb90902SMauro Carvalho Chehab
395f5889e70SMauro Carvalho Chehab	$max_size_status = length($notcompat) if (length($notcompat) > $max_size_status);
396f5889e70SMauro Carvalho Chehab
397f5889e70SMauro Carvalho Chehab	# Ensure that the status will fit
398f5889e70SMauro Carvalho Chehab	my $min_status_size = $max_size_status + $max_size_arch + 6;
399f5889e70SMauro Carvalho Chehab	$status_size = $min_status_size if ($status_size < $min_status_size);
400f5889e70SMauro Carvalho Chehab
401dbb90902SMauro Carvalho Chehab
402ba813f7cSMauro Carvalho Chehab	my $cur_subsys = "";
40352a4be3fSMauro Carvalho Chehab	foreach my $name (sort {
404ba813f7cSMauro Carvalho Chehab				($data{$a}->{subsys} cmp $data{$b}->{subsys}) or
405ca908577SMauro Carvalho Chehab				("\L$a" cmp "\L$b")
40652a4be3fSMauro Carvalho Chehab			       } keys %data) {
407ba813f7cSMauro Carvalho Chehab
408ba813f7cSMauro Carvalho Chehab		if ($cur_subsys ne $data{$name}->{subsys}) {
409ba813f7cSMauro Carvalho Chehab			if ($cur_subsys ne "") {
410ba813f7cSMauro Carvalho Chehab				printf "\n";
411ba813f7cSMauro Carvalho Chehab			}
412ba813f7cSMauro Carvalho Chehab
413ba813f7cSMauro Carvalho Chehab			$cur_subsys = $data{$name}->{subsys};
414ba813f7cSMauro Carvalho Chehab
415ba813f7cSMauro Carvalho Chehab			my $title = "Subsystem: $cur_subsys";
416ba813f7cSMauro Carvalho Chehab			print "$title\n";
417ba813f7cSMauro Carvalho Chehab			print "=" x length($title) . "\n\n";
418ba813f7cSMauro Carvalho Chehab
419dbb90902SMauro Carvalho Chehab
420dbb90902SMauro Carvalho Chehab			matrix_lines($desc_size, $status_size, 0);
421dbb90902SMauro Carvalho Chehab
422ba813f7cSMauro Carvalho Chehab			printf "|%-${max_size_name}s", $h_name;
423dbb90902SMauro Carvalho Chehab			printf "|%-${desc_size}s", $desc_title;
424ba813f7cSMauro Carvalho Chehab
425dbb90902SMauro Carvalho Chehab			printf "|%-${status_size}s|\n", "Status per architecture";
426dbb90902SMauro Carvalho Chehab			matrix_lines($desc_size, $status_size, 1);
427ba813f7cSMauro Carvalho Chehab		}
42852a4be3fSMauro Carvalho Chehab
42952a4be3fSMauro Carvalho Chehab		my %arch_table = %{$data{$name}->{table}};
430dbb90902SMauro Carvalho Chehab		my $cur_status = "";
43152a4be3fSMauro Carvalho Chehab
432f5889e70SMauro Carvalho Chehab		my (@lines, @descs);
433dbb90902SMauro Carvalho Chehab		my $line = "";
434dbb90902SMauro Carvalho Chehab		foreach my $arch (sort {
4354fa32f87SMauro Carvalho Chehab					($arch_table{$b} cmp $arch_table{$a}) or
436dbb90902SMauro Carvalho Chehab					("\L$a" cmp "\L$b")
437dbb90902SMauro Carvalho Chehab				       } keys %arch_table) {
438dbb90902SMauro Carvalho Chehab
439dbb90902SMauro Carvalho Chehab			my $status = $arch_table{$arch};
440dbb90902SMauro Carvalho Chehab
441dbb90902SMauro Carvalho Chehab			if ($status eq "---") {
442f5889e70SMauro Carvalho Chehab				$status = $notcompat;
443dbb90902SMauro Carvalho Chehab			}
444dbb90902SMauro Carvalho Chehab
445dbb90902SMauro Carvalho Chehab			if ($status ne $cur_status) {
446dbb90902SMauro Carvalho Chehab				if ($line ne "") {
447dbb90902SMauro Carvalho Chehab					push @lines, $line;
448dbb90902SMauro Carvalho Chehab					$line = "";
449dbb90902SMauro Carvalho Chehab				}
450dbb90902SMauro Carvalho Chehab				$line = "- **" . $status . "**: " . $arch;
451dbb90902SMauro Carvalho Chehab			} elsif (length($line) + length ($arch) + 2 < $status_size) {
452dbb90902SMauro Carvalho Chehab				$line .= ", " . $arch;
453dbb90902SMauro Carvalho Chehab			} else {
454dbb90902SMauro Carvalho Chehab				push @lines, $line;
455dbb90902SMauro Carvalho Chehab				$line = "  " . $arch;
456dbb90902SMauro Carvalho Chehab			}
457dbb90902SMauro Carvalho Chehab			$cur_status = $status;
458dbb90902SMauro Carvalho Chehab		}
459dbb90902SMauro Carvalho Chehab		push @lines, $line if ($line ne "");
460dbb90902SMauro Carvalho Chehab
461f5889e70SMauro Carvalho Chehab		my $description = $data{$name}->{description};
462f5889e70SMauro Carvalho Chehab		while (length($description) > $desc_size) {
463f5889e70SMauro Carvalho Chehab			my $d = substr $description, 0, $desc_size;
464f5889e70SMauro Carvalho Chehab
465f5889e70SMauro Carvalho Chehab			# Ensure that it will end on a space
466f5889e70SMauro Carvalho Chehab			# if it can't, it means that the size is too small
467f5889e70SMauro Carvalho Chehab			# Instead of aborting it, let's print what we have
468f5889e70SMauro Carvalho Chehab			if (!($d =~ s/^(.*)\s+.*/$1/)) {
469f5889e70SMauro Carvalho Chehab				$d = substr $d, 0, -1;
470f5889e70SMauro Carvalho Chehab				push @descs, "$d\\";
471f5889e70SMauro Carvalho Chehab				$description =~ s/^\Q$d\E//;
472f5889e70SMauro Carvalho Chehab			} else {
473f5889e70SMauro Carvalho Chehab				push @descs, $d;
474f5889e70SMauro Carvalho Chehab				$description =~ s/^\Q$d\E\s+//;
475f5889e70SMauro Carvalho Chehab			}
476f5889e70SMauro Carvalho Chehab		}
477f5889e70SMauro Carvalho Chehab		push @descs, $description;
478f5889e70SMauro Carvalho Chehab
479f5889e70SMauro Carvalho Chehab		# Ensure that the full description will be printed
480f5889e70SMauro Carvalho Chehab		push @lines, "" while (scalar(@lines) < 2 + scalar(@descs));
481dbb90902SMauro Carvalho Chehab
482dbb90902SMauro Carvalho Chehab		my $ln = 0;
483dbb90902SMauro Carvalho Chehab		for my $line(@lines) {
484dbb90902SMauro Carvalho Chehab			if (!$ln) {
485dbb90902SMauro Carvalho Chehab				printf "|%-${max_size_name}s", $name;
486dbb90902SMauro Carvalho Chehab				printf "|%-${desc_size}s", "``" . $data{$name}->{kconfig} . "``";
487f5889e70SMauro Carvalho Chehab			} elsif ($ln >= 2 && scalar(@descs)) {
488ba813f7cSMauro Carvalho Chehab				printf "|%-${max_size_name}s", "";
489f5889e70SMauro Carvalho Chehab				printf "|%-${desc_size}s", shift @descs;
490dbb90902SMauro Carvalho Chehab			} else {
491dbb90902SMauro Carvalho Chehab				printf "|%-${max_size_name}s", "";
492dbb90902SMauro Carvalho Chehab				printf "|%-${desc_size}s", "";
49352a4be3fSMauro Carvalho Chehab			}
494dbb90902SMauro Carvalho Chehab
495dbb90902SMauro Carvalho Chehab			printf "|%-${status_size}s|\n", $line;
496dbb90902SMauro Carvalho Chehab
497dbb90902SMauro Carvalho Chehab			$ln++;
49852a4be3fSMauro Carvalho Chehab		}
499dbb90902SMauro Carvalho Chehab		matrix_lines($desc_size, $status_size, 0);
500ba813f7cSMauro Carvalho Chehab	}
50152a4be3fSMauro Carvalho Chehab}
50252a4be3fSMauro Carvalho Chehab
50352a4be3fSMauro Carvalho Chehab
50452a4be3fSMauro Carvalho Chehab#
50552a4be3fSMauro Carvalho Chehab# Parses all feature files located at $prefix dir
50652a4be3fSMauro Carvalho Chehab#
50752a4be3fSMauro Carvalho Chehabfind({wanted =>\&parse_feat, no_chdir => 1}, $prefix);
50852a4be3fSMauro Carvalho Chehab
50952a4be3fSMauro Carvalho Chehabprint STDERR Data::Dumper->Dump([\%data], [qw(*data)]) if ($debug);
51052a4be3fSMauro Carvalho Chehab
51152a4be3fSMauro Carvalho Chehab#
51252a4be3fSMauro Carvalho Chehab# Handles the command
51352a4be3fSMauro Carvalho Chehab#
51452a4be3fSMauro Carvalho Chehabif ($cmd eq "current") {
51552a4be3fSMauro Carvalho Chehab	$arch = qx(uname -m | sed 's/x86_64/x86/' | sed 's/i386/x86/');
51652a4be3fSMauro Carvalho Chehab	$arch =~s/\s+$//;
51752a4be3fSMauro Carvalho Chehab}
51852a4be3fSMauro Carvalho Chehab
519ca908577SMauro Carvalho Chehabif ($cmd eq "ls" or $cmd eq "list") {
520ca908577SMauro Carvalho Chehab	if (!$arch) {
521ca908577SMauro Carvalho Chehab		$arch = qx(uname -m | sed 's/x86_64/x86/' | sed 's/i386/x86/');
522ca908577SMauro Carvalho Chehab		$arch =~s/\s+$//;
523ca908577SMauro Carvalho Chehab	}
524ca908577SMauro Carvalho Chehab
525ca908577SMauro Carvalho Chehab	list_arch_features;
526ca908577SMauro Carvalho Chehab
527ca908577SMauro Carvalho Chehab	exit;
528ca908577SMauro Carvalho Chehab}
529ca908577SMauro Carvalho Chehab
53052a4be3fSMauro Carvalho Chehabif ($cmd ne "validate") {
53152a4be3fSMauro Carvalho Chehab	if ($arch) {
53252a4be3fSMauro Carvalho Chehab		output_arch_table;
53352a4be3fSMauro Carvalho Chehab	} elsif ($feat) {
53452a4be3fSMauro Carvalho Chehab		output_feature;
53552a4be3fSMauro Carvalho Chehab	} else {
53652a4be3fSMauro Carvalho Chehab		output_matrix;
53752a4be3fSMauro Carvalho Chehab	}
53852a4be3fSMauro Carvalho Chehab}
53952a4be3fSMauro Carvalho Chehab
54052a4be3fSMauro Carvalho Chehab__END__
54152a4be3fSMauro Carvalho Chehab
54252a4be3fSMauro Carvalho Chehab=head1 NAME
54352a4be3fSMauro Carvalho Chehab
54452a4be3fSMauro Carvalho Chehabget_feat.pl - parse the Linux Feature files and produce a ReST book.
54552a4be3fSMauro Carvalho Chehab
54652a4be3fSMauro Carvalho Chehab=head1 SYNOPSIS
54752a4be3fSMauro Carvalho Chehab
548ca908577SMauro Carvalho ChehabB<get_feat.pl> [--debug] [--man] [--help] [--dir=<dir>] [--arch=<arch>]
549ca908577SMauro Carvalho Chehab	       [--feature=<feature>|--feat=<feature>] <COMAND> [<ARGUMENT>]
55052a4be3fSMauro Carvalho Chehab
55152a4be3fSMauro Carvalho ChehabWhere <COMMAND> can be:
55252a4be3fSMauro Carvalho Chehab
55352a4be3fSMauro Carvalho Chehab=over 8
55452a4be3fSMauro Carvalho Chehab
555ca908577SMauro Carvalho ChehabB<current>               - output table in ReST compatible ASCII format
556ca908577SMauro Carvalho Chehab			   with features for this machine's architecture
55752a4be3fSMauro Carvalho Chehab
558ca908577SMauro Carvalho ChehabB<rest>                  - output table(s)  in ReST compatible ASCII format
559ca908577SMauro Carvalho Chehab			   with features in ReST markup language. The output
560ca908577SMauro Carvalho Chehab			   is affected by --arch or --feat/--feature flags.
56152a4be3fSMauro Carvalho Chehab
562ca908577SMauro Carvalho ChehabB<validate>              - validate the contents of the files under
563ca908577SMauro Carvalho Chehab			   Documentation/features.
564ca908577SMauro Carvalho Chehab
565ca908577SMauro Carvalho ChehabB<ls> or B<list>         - list features for this machine's architecture,
566ca908577SMauro Carvalho Chehab			   using an easier to parse format.
567ca908577SMauro Carvalho Chehab			   The output is affected by --arch flag.
56852a4be3fSMauro Carvalho Chehab
56952a4be3fSMauro Carvalho Chehab=back
57052a4be3fSMauro Carvalho Chehab
57152a4be3fSMauro Carvalho Chehab=head1 OPTIONS
57252a4be3fSMauro Carvalho Chehab
57352a4be3fSMauro Carvalho Chehab=over 8
57452a4be3fSMauro Carvalho Chehab
57552a4be3fSMauro Carvalho Chehab=item B<--arch>
57652a4be3fSMauro Carvalho Chehab
57752a4be3fSMauro Carvalho ChehabOutput features for an specific architecture, optionally filtering for
57852a4be3fSMauro Carvalho Chehaba single specific feature.
57952a4be3fSMauro Carvalho Chehab
580ca908577SMauro Carvalho Chehab=item B<--feat> or B<--feature>
58152a4be3fSMauro Carvalho Chehab
582ca908577SMauro Carvalho ChehabOutput features for a single specific feature.
58352a4be3fSMauro Carvalho Chehab
58452a4be3fSMauro Carvalho Chehab=item B<--dir>
58552a4be3fSMauro Carvalho Chehab
58652a4be3fSMauro Carvalho ChehabChanges the location of the Feature files. By default, it uses
58752a4be3fSMauro Carvalho Chehabthe Documentation/features directory.
58852a4be3fSMauro Carvalho Chehab
58901096e5cSMauro Carvalho Chehab=item B<--enable-fname>
59001096e5cSMauro Carvalho Chehab
59101096e5cSMauro Carvalho ChehabPrints the file name of the feature files. This can be used in order to
59201096e5cSMauro Carvalho Chehabtrack dependencies during documentation build.
59301096e5cSMauro Carvalho Chehab
59452a4be3fSMauro Carvalho Chehab=item B<--debug>
59552a4be3fSMauro Carvalho Chehab
59652a4be3fSMauro Carvalho ChehabPut the script in verbose mode, useful for debugging. Can be called multiple
59752a4be3fSMauro Carvalho Chehabtimes, to increase verbosity.
59852a4be3fSMauro Carvalho Chehab
59952a4be3fSMauro Carvalho Chehab=item B<--help>
60052a4be3fSMauro Carvalho Chehab
60152a4be3fSMauro Carvalho ChehabPrints a brief help message and exits.
60252a4be3fSMauro Carvalho Chehab
60352a4be3fSMauro Carvalho Chehab=item B<--man>
60452a4be3fSMauro Carvalho Chehab
60552a4be3fSMauro Carvalho ChehabPrints the manual page and exits.
60652a4be3fSMauro Carvalho Chehab
60752a4be3fSMauro Carvalho Chehab=back
60852a4be3fSMauro Carvalho Chehab
60952a4be3fSMauro Carvalho Chehab=head1 DESCRIPTION
61052a4be3fSMauro Carvalho Chehab
61152a4be3fSMauro Carvalho ChehabParse the Linux feature files from Documentation/features (by default),
61252a4be3fSMauro Carvalho Chehaboptionally producing results at ReST format.
61352a4be3fSMauro Carvalho Chehab
61452a4be3fSMauro Carvalho ChehabIt supports output data per architecture, per feature or a
61552a4be3fSMauro Carvalho Chehabfeature x arch matrix.
61652a4be3fSMauro Carvalho Chehab
61752a4be3fSMauro Carvalho ChehabWhen used with B<rest> command, it will use either one of the tree formats:
61852a4be3fSMauro Carvalho Chehab
61952a4be3fSMauro Carvalho ChehabIf neither B<--arch> or B<--feature> arguments are used, it will output a
62052a4be3fSMauro Carvalho Chehabmatrix with features per architecture.
62152a4be3fSMauro Carvalho Chehab
62252a4be3fSMauro Carvalho ChehabIf B<--arch> argument is used, it will output the features availability for
62352a4be3fSMauro Carvalho Chehaba given architecture.
62452a4be3fSMauro Carvalho Chehab
62552a4be3fSMauro Carvalho ChehabIf B<--feat> argument is used, it will output the content of the feature
62652a4be3fSMauro Carvalho Chehabfile using ReStructured Text markup.
62752a4be3fSMauro Carvalho Chehab
62852a4be3fSMauro Carvalho Chehab=head1 BUGS
62952a4be3fSMauro Carvalho Chehab
63052a4be3fSMauro Carvalho ChehabReport bugs to Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
63152a4be3fSMauro Carvalho Chehab
63252a4be3fSMauro Carvalho Chehab=head1 COPYRIGHT
63352a4be3fSMauro Carvalho Chehab
63452a4be3fSMauro Carvalho ChehabCopyright (c) 2019 by Mauro Carvalho Chehab <mchehab+samsung@kernel.org>.
63552a4be3fSMauro Carvalho Chehab
63652a4be3fSMauro Carvalho ChehabLicense GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>.
63752a4be3fSMauro Carvalho Chehab
63852a4be3fSMauro Carvalho ChehabThis is free software: you are free to change and redistribute it.
63952a4be3fSMauro Carvalho ChehabThere is NO WARRANTY, to the extent permitted by law.
64052a4be3fSMauro Carvalho Chehab
64152a4be3fSMauro Carvalho Chehab=cut
642