xref: /openbmc/linux/scripts/get_feat.pl (revision f5889e70)
152a4be3fSMauro Carvalho Chehab#!/usr/bin/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;
16ca908577SMauro Carvalho Chehab
17ca908577SMauro Carvalho Chehabmy $basename = abs_path($0);
18ca908577SMauro Carvalho Chehab$basename =~ s,/[^/]+$,/,;
19ca908577SMauro Carvalho Chehab
20ca908577SMauro Carvalho Chehabmy $prefix=$basename . "../Documentation/features";
2152a4be3fSMauro Carvalho Chehab
22*f5889e70SMauro Carvalho Chehab# Used only at for full features output. The script will auto-adjust
23*f5889e70SMauro Carvalho Chehab# such values for the minimal possible values
24*f5889e70SMauro Carvalho Chehabmy $status_size = 1;
25*f5889e70SMauro Carvalho Chehabmy $description_size = 1;
26*f5889e70SMauro Carvalho Chehab
2752a4be3fSMauro Carvalho ChehabGetOptions(
2852a4be3fSMauro Carvalho Chehab	"debug|d+" => \$debug,
2952a4be3fSMauro Carvalho Chehab	"dir=s" => \$prefix,
3052a4be3fSMauro Carvalho Chehab	'help|?' => \$help,
3152a4be3fSMauro Carvalho Chehab	'arch=s' => \$arch,
3252a4be3fSMauro Carvalho Chehab	'feat=s' => \$feat,
33ca908577SMauro Carvalho Chehab	'feature=s' => \$feat,
3452a4be3fSMauro Carvalho Chehab	man => \$man
3552a4be3fSMauro Carvalho Chehab) or pod2usage(2);
3652a4be3fSMauro Carvalho Chehab
3752a4be3fSMauro Carvalho Chehabpod2usage(1) if $help;
3852a4be3fSMauro Carvalho Chehabpod2usage(-exitstatus => 0, -verbose => 2) if $man;
3952a4be3fSMauro Carvalho Chehab
40ca908577SMauro Carvalho Chehabpod2usage(1) if (scalar @ARGV < 1 || @ARGV > 2);
4152a4be3fSMauro Carvalho Chehab
4252a4be3fSMauro Carvalho Chehabmy ($cmd, $arg) = @ARGV;
4352a4be3fSMauro Carvalho Chehab
44ca908577SMauro Carvalho Chehabpod2usage(2) if ($cmd ne "current" && $cmd ne "rest" && $cmd ne "validate"
45ca908577SMauro Carvalho Chehab		&& $cmd ne "ls" && $cmd ne "list");
4652a4be3fSMauro Carvalho Chehab
4752a4be3fSMauro Carvalho Chehabrequire Data::Dumper if ($debug);
4852a4be3fSMauro Carvalho Chehab
4952a4be3fSMauro Carvalho Chehabmy %data;
5052a4be3fSMauro Carvalho Chehabmy %archs;
5152a4be3fSMauro Carvalho Chehab
5252a4be3fSMauro Carvalho Chehab#
5352a4be3fSMauro Carvalho Chehab# Displays an error message, printing file name and line
5452a4be3fSMauro Carvalho Chehab#
5552a4be3fSMauro Carvalho Chehabsub parse_error($$$$) {
5652a4be3fSMauro Carvalho Chehab	my ($file, $ln, $msg, $data) = @_;
5752a4be3fSMauro Carvalho Chehab
5852a4be3fSMauro Carvalho Chehab	$data =~ s/\s+$/\n/;
5952a4be3fSMauro Carvalho Chehab
6052a4be3fSMauro Carvalho Chehab	print STDERR "Warning: file $file#$ln:\n\t$msg";
6152a4be3fSMauro Carvalho Chehab
6252a4be3fSMauro Carvalho Chehab	if ($data ne "") {
6352a4be3fSMauro Carvalho Chehab		print STDERR ". Line\n\t\t$data";
6452a4be3fSMauro Carvalho Chehab	} else {
6552a4be3fSMauro Carvalho Chehab	    print STDERR "\n";
6652a4be3fSMauro Carvalho Chehab	}
6752a4be3fSMauro Carvalho Chehab}
6852a4be3fSMauro Carvalho Chehab
6952a4be3fSMauro Carvalho Chehab#
7052a4be3fSMauro Carvalho Chehab# Parse a features file, storing its contents at %data
7152a4be3fSMauro Carvalho Chehab#
7252a4be3fSMauro Carvalho Chehab
7352a4be3fSMauro Carvalho Chehabmy $h_name = "Feature";
7452a4be3fSMauro Carvalho Chehabmy $h_kconfig = "Kconfig";
7552a4be3fSMauro Carvalho Chehabmy $h_description = "Description";
7652a4be3fSMauro Carvalho Chehabmy $h_subsys = "Subsystem";
7752a4be3fSMauro Carvalho Chehabmy $h_status = "Status";
7852a4be3fSMauro Carvalho Chehabmy $h_arch = "Architecture";
7952a4be3fSMauro Carvalho Chehab
8052a4be3fSMauro Carvalho Chehabmy $max_size_name = length($h_name);
8152a4be3fSMauro Carvalho Chehabmy $max_size_kconfig = length($h_kconfig);
8252a4be3fSMauro Carvalho Chehabmy $max_size_description = length($h_description);
8352a4be3fSMauro Carvalho Chehabmy $max_size_subsys = length($h_subsys);
8452a4be3fSMauro Carvalho Chehabmy $max_size_status = length($h_status);
85*f5889e70SMauro Carvalho Chehab
86*f5889e70SMauro Carvalho Chehabmy $max_size_arch = 0;
87*f5889e70SMauro Carvalho Chehabmy $max_size_arch_with_header;
88*f5889e70SMauro Carvalho Chehabmy $max_description_word = 0;
8952a4be3fSMauro Carvalho Chehab
9052a4be3fSMauro Carvalho Chehabsub parse_feat {
9152a4be3fSMauro Carvalho Chehab	my $file = $File::Find::name;
9252a4be3fSMauro Carvalho Chehab
9352a4be3fSMauro Carvalho Chehab	my $mode = (stat($file))[2];
9452a4be3fSMauro Carvalho Chehab	return if ($mode & S_IFDIR);
9552a4be3fSMauro Carvalho Chehab	return if ($file =~ m,($prefix)/arch-support.txt,);
9652a4be3fSMauro Carvalho Chehab	return if (!($file =~ m,arch-support.txt$,));
9752a4be3fSMauro Carvalho Chehab
9852a4be3fSMauro Carvalho Chehab	my $subsys = "";
9952a4be3fSMauro Carvalho Chehab	$subsys = $2 if ( m,.*($prefix)/([^/]+).*,);
10052a4be3fSMauro Carvalho Chehab
10152a4be3fSMauro Carvalho Chehab	if (length($subsys) > $max_size_subsys) {
10252a4be3fSMauro Carvalho Chehab		$max_size_subsys = length($subsys);
10352a4be3fSMauro Carvalho Chehab	}
10452a4be3fSMauro Carvalho Chehab
10552a4be3fSMauro Carvalho Chehab	my $name;
10652a4be3fSMauro Carvalho Chehab	my $kconfig;
10752a4be3fSMauro Carvalho Chehab	my $description;
10852a4be3fSMauro Carvalho Chehab	my $comments = "";
10952a4be3fSMauro Carvalho Chehab	my $last_status;
11052a4be3fSMauro Carvalho Chehab	my $ln;
11152a4be3fSMauro Carvalho Chehab	my %arch_table;
11252a4be3fSMauro Carvalho Chehab
11352a4be3fSMauro Carvalho Chehab	print STDERR "Opening $file\n" if ($debug > 1);
11452a4be3fSMauro Carvalho Chehab	open IN, $file;
11552a4be3fSMauro Carvalho Chehab
11652a4be3fSMauro Carvalho Chehab	while(<IN>) {
11752a4be3fSMauro Carvalho Chehab		$ln++;
11852a4be3fSMauro Carvalho Chehab
11952a4be3fSMauro Carvalho Chehab		if (m/^\#\s+Feature\s+name:\s*(.*\S)/) {
12052a4be3fSMauro Carvalho Chehab			$name = $1;
12152a4be3fSMauro Carvalho Chehab			if (length($name) > $max_size_name) {
12252a4be3fSMauro Carvalho Chehab				$max_size_name = length($name);
12352a4be3fSMauro Carvalho Chehab			}
12452a4be3fSMauro Carvalho Chehab			next;
12552a4be3fSMauro Carvalho Chehab		}
12652a4be3fSMauro Carvalho Chehab		if (m/^\#\s+Kconfig:\s*(.*\S)/) {
12752a4be3fSMauro Carvalho Chehab			$kconfig = $1;
12852a4be3fSMauro Carvalho Chehab			if (length($kconfig) > $max_size_kconfig) {
12952a4be3fSMauro Carvalho Chehab				$max_size_kconfig = length($kconfig);
13052a4be3fSMauro Carvalho Chehab			}
13152a4be3fSMauro Carvalho Chehab			next;
13252a4be3fSMauro Carvalho Chehab		}
13352a4be3fSMauro Carvalho Chehab		if (m/^\#\s+description:\s*(.*\S)/) {
13452a4be3fSMauro Carvalho Chehab			$description = $1;
13552a4be3fSMauro Carvalho Chehab			if (length($description) > $max_size_description) {
13652a4be3fSMauro Carvalho Chehab				$max_size_description = length($description);
13752a4be3fSMauro Carvalho Chehab			}
138*f5889e70SMauro Carvalho Chehab
139*f5889e70SMauro Carvalho Chehab			foreach my $word (split /\s+/, $description) {
140*f5889e70SMauro Carvalho Chehab				if (length($word) > $max_description_word) {
141*f5889e70SMauro Carvalho Chehab					$max_description_word = length($word);
142*f5889e70SMauro Carvalho Chehab				}
143*f5889e70SMauro Carvalho Chehab			}
144*f5889e70SMauro Carvalho Chehab
14552a4be3fSMauro Carvalho Chehab			next;
14652a4be3fSMauro Carvalho Chehab		}
14752a4be3fSMauro Carvalho Chehab		next if (m/^\\s*$/);
14852a4be3fSMauro Carvalho Chehab		next if (m/^\s*\-+\s*$/);
14952a4be3fSMauro Carvalho Chehab		next if (m/^\s*\|\s*arch\s*\|\s*status\s*\|\s*$/);
15052a4be3fSMauro Carvalho Chehab
15152a4be3fSMauro Carvalho Chehab		if (m/^\#\s*(.*)/) {
15252a4be3fSMauro Carvalho Chehab			$comments .= "$1\n";
15352a4be3fSMauro Carvalho Chehab			next;
15452a4be3fSMauro Carvalho Chehab		}
15552a4be3fSMauro Carvalho Chehab		if (m/^\s*\|\s*(\S+):\s*\|\s*(\S+)\s*\|\s*$/) {
15652a4be3fSMauro Carvalho Chehab			my $a = $1;
15752a4be3fSMauro Carvalho Chehab			my $status = $2;
15852a4be3fSMauro Carvalho Chehab
15952a4be3fSMauro Carvalho Chehab			if (length($status) > $max_size_status) {
16052a4be3fSMauro Carvalho Chehab				$max_size_status = length($status);
16152a4be3fSMauro Carvalho Chehab			}
16252a4be3fSMauro Carvalho Chehab			if (length($a) > $max_size_arch) {
16352a4be3fSMauro Carvalho Chehab				$max_size_arch = length($a);
16452a4be3fSMauro Carvalho Chehab			}
16552a4be3fSMauro Carvalho Chehab
16652a4be3fSMauro Carvalho Chehab			$status = "---" if ($status =~ m/^\.\.$/);
16752a4be3fSMauro Carvalho Chehab
16852a4be3fSMauro Carvalho Chehab			$archs{$a} = 1;
16952a4be3fSMauro Carvalho Chehab			$arch_table{$a} = $status;
17052a4be3fSMauro Carvalho Chehab			next;
17152a4be3fSMauro Carvalho Chehab		}
17252a4be3fSMauro Carvalho Chehab
17352a4be3fSMauro Carvalho Chehab		#Everything else is an error
17452a4be3fSMauro Carvalho Chehab		parse_error($file, $ln, "line is invalid", $_);
17552a4be3fSMauro Carvalho Chehab	}
17652a4be3fSMauro Carvalho Chehab	close IN;
17752a4be3fSMauro Carvalho Chehab
17852a4be3fSMauro Carvalho Chehab	if (!$name) {
17952a4be3fSMauro Carvalho Chehab		parse_error($file, $ln, "Feature name not found", "");
18052a4be3fSMauro Carvalho Chehab		return;
18152a4be3fSMauro Carvalho Chehab	}
18252a4be3fSMauro Carvalho Chehab
18352a4be3fSMauro Carvalho Chehab	parse_error($file, $ln, "Subsystem not found", "") if (!$subsys);
18452a4be3fSMauro Carvalho Chehab	parse_error($file, $ln, "Kconfig not found", "") if (!$kconfig);
18552a4be3fSMauro Carvalho Chehab	parse_error($file, $ln, "Description not found", "") if (!$description);
18652a4be3fSMauro Carvalho Chehab
18752a4be3fSMauro Carvalho Chehab	if (!%arch_table) {
18852a4be3fSMauro Carvalho Chehab		parse_error($file, $ln, "Architecture table not found", "");
18952a4be3fSMauro Carvalho Chehab		return;
19052a4be3fSMauro Carvalho Chehab	}
19152a4be3fSMauro Carvalho Chehab
19252a4be3fSMauro Carvalho Chehab	$data{$name}->{where} = $file;
19352a4be3fSMauro Carvalho Chehab	$data{$name}->{subsys} = $subsys;
19452a4be3fSMauro Carvalho Chehab	$data{$name}->{kconfig} = $kconfig;
19552a4be3fSMauro Carvalho Chehab	$data{$name}->{description} = $description;
19652a4be3fSMauro Carvalho Chehab	$data{$name}->{comments} = $comments;
19752a4be3fSMauro Carvalho Chehab	$data{$name}->{table} = \%arch_table;
198*f5889e70SMauro Carvalho Chehab
199*f5889e70SMauro Carvalho Chehab	$max_size_arch_with_header = $max_size_arch + length($h_arch);
20052a4be3fSMauro Carvalho Chehab}
20152a4be3fSMauro Carvalho Chehab
20252a4be3fSMauro Carvalho Chehab#
20352a4be3fSMauro Carvalho Chehab# Output feature(s) for a given architecture
20452a4be3fSMauro Carvalho Chehab#
20552a4be3fSMauro Carvalho Chehabsub output_arch_table {
20652a4be3fSMauro Carvalho Chehab	my $title = "Feature status on $arch architecture";
20752a4be3fSMauro Carvalho Chehab
20852a4be3fSMauro Carvalho Chehab	print "=" x length($title) . "\n";
20952a4be3fSMauro Carvalho Chehab	print "$title\n";
21052a4be3fSMauro Carvalho Chehab	print "=" x length($title) . "\n\n";
21152a4be3fSMauro Carvalho Chehab
21252a4be3fSMauro Carvalho Chehab	print "=" x $max_size_subsys;
21352a4be3fSMauro Carvalho Chehab	print "  ";
21452a4be3fSMauro Carvalho Chehab	print "=" x $max_size_name;
21552a4be3fSMauro Carvalho Chehab	print "  ";
21652a4be3fSMauro Carvalho Chehab	print "=" x $max_size_kconfig;
21752a4be3fSMauro Carvalho Chehab	print "  ";
21852a4be3fSMauro Carvalho Chehab	print "=" x $max_size_status;
21952a4be3fSMauro Carvalho Chehab	print "  ";
22052a4be3fSMauro Carvalho Chehab	print "=" x $max_size_description;
22152a4be3fSMauro Carvalho Chehab	print "\n";
22252a4be3fSMauro Carvalho Chehab	printf "%-${max_size_subsys}s  ", $h_subsys;
22352a4be3fSMauro Carvalho Chehab	printf "%-${max_size_name}s  ", $h_name;
22452a4be3fSMauro Carvalho Chehab	printf "%-${max_size_kconfig}s  ", $h_kconfig;
22552a4be3fSMauro Carvalho Chehab	printf "%-${max_size_status}s  ", $h_status;
22652a4be3fSMauro Carvalho Chehab	printf "%-${max_size_description}s\n", $h_description;
22752a4be3fSMauro Carvalho Chehab	print "=" x $max_size_subsys;
22852a4be3fSMauro Carvalho Chehab	print "  ";
22952a4be3fSMauro Carvalho Chehab	print "=" x $max_size_name;
23052a4be3fSMauro Carvalho Chehab	print "  ";
23152a4be3fSMauro Carvalho Chehab	print "=" x $max_size_kconfig;
23252a4be3fSMauro Carvalho Chehab	print "  ";
23352a4be3fSMauro Carvalho Chehab	print "=" x $max_size_status;
23452a4be3fSMauro Carvalho Chehab	print "  ";
23552a4be3fSMauro Carvalho Chehab	print "=" x $max_size_description;
23652a4be3fSMauro Carvalho Chehab	print "\n";
23752a4be3fSMauro Carvalho Chehab
23852a4be3fSMauro Carvalho Chehab	foreach my $name (sort {
23952a4be3fSMauro Carvalho Chehab				($data{$a}->{subsys} cmp $data{$b}->{subsys}) ||
240ca908577SMauro Carvalho Chehab				("\L$a" cmp "\L$b")
24152a4be3fSMauro Carvalho Chehab			       } keys %data) {
24252a4be3fSMauro Carvalho Chehab		next if ($feat && $name ne $feat);
24352a4be3fSMauro Carvalho Chehab
24452a4be3fSMauro Carvalho Chehab		my %arch_table = %{$data{$name}->{table}};
24552a4be3fSMauro Carvalho Chehab		printf "%-${max_size_subsys}s  ", $data{$name}->{subsys};
24652a4be3fSMauro Carvalho Chehab		printf "%-${max_size_name}s  ", $name;
24752a4be3fSMauro Carvalho Chehab		printf "%-${max_size_kconfig}s  ", $data{$name}->{kconfig};
24852a4be3fSMauro Carvalho Chehab		printf "%-${max_size_status}s  ", $arch_table{$arch};
249ca908577SMauro Carvalho Chehab		printf "%-s\n", $data{$name}->{description};
25052a4be3fSMauro Carvalho Chehab	}
25152a4be3fSMauro Carvalho Chehab
25252a4be3fSMauro Carvalho Chehab	print "=" x $max_size_subsys;
25352a4be3fSMauro Carvalho Chehab	print "  ";
25452a4be3fSMauro Carvalho Chehab	print "=" x $max_size_name;
25552a4be3fSMauro Carvalho Chehab	print "  ";
25652a4be3fSMauro Carvalho Chehab	print "=" x $max_size_kconfig;
25752a4be3fSMauro Carvalho Chehab	print "  ";
25852a4be3fSMauro Carvalho Chehab	print "=" x $max_size_status;
25952a4be3fSMauro Carvalho Chehab	print "  ";
26052a4be3fSMauro Carvalho Chehab	print "=" x $max_size_description;
26152a4be3fSMauro Carvalho Chehab	print "\n";
26252a4be3fSMauro Carvalho Chehab}
26352a4be3fSMauro Carvalho Chehab
26452a4be3fSMauro Carvalho Chehab#
265ca908577SMauro Carvalho Chehab# list feature(s) for a given architecture
266ca908577SMauro Carvalho Chehab#
267ca908577SMauro Carvalho Chehabsub list_arch_features {
268ca908577SMauro Carvalho Chehab	print "#\n# Kernel feature support matrix of the '$arch' architecture:\n#\n";
269ca908577SMauro Carvalho Chehab
270ca908577SMauro Carvalho Chehab	foreach my $name (sort {
271ca908577SMauro Carvalho Chehab				($data{$a}->{subsys} cmp $data{$b}->{subsys}) ||
272ca908577SMauro Carvalho Chehab				("\L$a" cmp "\L$b")
273ca908577SMauro Carvalho Chehab			       } keys %data) {
274ca908577SMauro Carvalho Chehab		next if ($feat && $name ne $feat);
275ca908577SMauro Carvalho Chehab
276ca908577SMauro Carvalho Chehab		my %arch_table = %{$data{$name}->{table}};
277ca908577SMauro Carvalho Chehab
278ca908577SMauro Carvalho Chehab		my $status = $arch_table{$arch};
279ca908577SMauro Carvalho Chehab		$status = " " x ((4 - length($status)) / 2) . $status;
280ca908577SMauro Carvalho Chehab
281ca908577SMauro Carvalho Chehab		printf " %${max_size_subsys}s/ ", $data{$name}->{subsys};
282ca908577SMauro Carvalho Chehab		printf "%-${max_size_name}s: ", $name;
283ca908577SMauro Carvalho Chehab		printf "%-5s|   ", $status;
284ca908577SMauro Carvalho Chehab		printf "%${max_size_kconfig}s # ", $data{$name}->{kconfig};
285ca908577SMauro Carvalho Chehab		printf " %s\n", $data{$name}->{description};
286ca908577SMauro Carvalho Chehab	}
287ca908577SMauro Carvalho Chehab}
288ca908577SMauro Carvalho Chehab
289ca908577SMauro Carvalho Chehab#
29052a4be3fSMauro Carvalho Chehab# Output a feature on all architectures
29152a4be3fSMauro Carvalho Chehab#
29252a4be3fSMauro Carvalho Chehabsub output_feature {
29352a4be3fSMauro Carvalho Chehab	my $title = "Feature $feat";
29452a4be3fSMauro Carvalho Chehab
29552a4be3fSMauro Carvalho Chehab	print "=" x length($title) . "\n";
29652a4be3fSMauro Carvalho Chehab	print "$title\n";
29752a4be3fSMauro Carvalho Chehab	print "=" x length($title) . "\n\n";
29852a4be3fSMauro Carvalho Chehab
29952a4be3fSMauro Carvalho Chehab	print ":Subsystem: $data{$feat}->{subsys} \n" if ($data{$feat}->{subsys});
30052a4be3fSMauro Carvalho Chehab	print ":Kconfig: $data{$feat}->{kconfig} \n" if ($data{$feat}->{kconfig});
30152a4be3fSMauro Carvalho Chehab
30252a4be3fSMauro Carvalho Chehab	my $desc = $data{$feat}->{description};
30352a4be3fSMauro Carvalho Chehab	$desc =~ s/^([a-z])/\U$1/;
30452a4be3fSMauro Carvalho Chehab	$desc =~ s/\.?\s*//;
30552a4be3fSMauro Carvalho Chehab	print "\n$desc.\n\n";
30652a4be3fSMauro Carvalho Chehab
30752a4be3fSMauro Carvalho Chehab	my $com = $data{$feat}->{comments};
30852a4be3fSMauro Carvalho Chehab	$com =~ s/^\s+//;
30952a4be3fSMauro Carvalho Chehab	$com =~ s/\s+$//;
31052a4be3fSMauro Carvalho Chehab	if ($com) {
31152a4be3fSMauro Carvalho Chehab		print "Comments\n";
31252a4be3fSMauro Carvalho Chehab		print "--------\n\n";
31352a4be3fSMauro Carvalho Chehab		print "$com\n\n";
31452a4be3fSMauro Carvalho Chehab	}
31552a4be3fSMauro Carvalho Chehab
316*f5889e70SMauro Carvalho Chehab	print "=" x $max_size_arch_with_header;
31752a4be3fSMauro Carvalho Chehab	print "  ";
31852a4be3fSMauro Carvalho Chehab	print "=" x $max_size_status;
31952a4be3fSMauro Carvalho Chehab	print "\n";
32052a4be3fSMauro Carvalho Chehab
32152a4be3fSMauro Carvalho Chehab	printf "%-${max_size_arch}s  ", $h_arch;
32252a4be3fSMauro Carvalho Chehab	printf "%-${max_size_status}s", $h_status . "\n";
32352a4be3fSMauro Carvalho Chehab
324*f5889e70SMauro Carvalho Chehab	print "=" x $max_size_arch_with_header;
32552a4be3fSMauro Carvalho Chehab	print "  ";
32652a4be3fSMauro Carvalho Chehab	print "=" x $max_size_status;
32752a4be3fSMauro Carvalho Chehab	print "\n";
32852a4be3fSMauro Carvalho Chehab
32952a4be3fSMauro Carvalho Chehab	my %arch_table = %{$data{$feat}->{table}};
33052a4be3fSMauro Carvalho Chehab	foreach my $arch (sort keys %arch_table) {
33152a4be3fSMauro Carvalho Chehab		printf "%-${max_size_arch}s  ", $arch;
33252a4be3fSMauro Carvalho Chehab		printf "%-${max_size_status}s\n", $arch_table{$arch};
33352a4be3fSMauro Carvalho Chehab	}
33452a4be3fSMauro Carvalho Chehab
335*f5889e70SMauro Carvalho Chehab	print "=" x $max_size_arch_with_header;
33652a4be3fSMauro Carvalho Chehab	print "  ";
33752a4be3fSMauro Carvalho Chehab	print "=" x $max_size_status;
33852a4be3fSMauro Carvalho Chehab	print "\n";
33952a4be3fSMauro Carvalho Chehab}
34052a4be3fSMauro Carvalho Chehab
34152a4be3fSMauro Carvalho Chehab#
34252a4be3fSMauro Carvalho Chehab# Output all features for all architectures
34352a4be3fSMauro Carvalho Chehab#
34452a4be3fSMauro Carvalho Chehab
345dbb90902SMauro Carvalho Chehabsub matrix_lines($$$) {
346dbb90902SMauro Carvalho Chehab	my $desc_size = shift;
347dbb90902SMauro Carvalho Chehab	my $status_size = shift;
348ba813f7cSMauro Carvalho Chehab	my $header = shift;
349ba813f7cSMauro Carvalho Chehab	my $fill;
350ba813f7cSMauro Carvalho Chehab	my $ln_marker;
35152a4be3fSMauro Carvalho Chehab
352ba813f7cSMauro Carvalho Chehab	if ($header) {
353ba813f7cSMauro Carvalho Chehab		$ln_marker = "=";
354ba813f7cSMauro Carvalho Chehab	} else {
355ba813f7cSMauro Carvalho Chehab		$ln_marker = "-";
35652a4be3fSMauro Carvalho Chehab	}
357ba813f7cSMauro Carvalho Chehab
358ba813f7cSMauro Carvalho Chehab	$fill = $ln_marker;
359ba813f7cSMauro Carvalho Chehab
360dbb90902SMauro Carvalho Chehab	print "+";
361ba813f7cSMauro Carvalho Chehab	print $fill x $max_size_name;
362ba813f7cSMauro Carvalho Chehab	print "+";
363dbb90902SMauro Carvalho Chehab	print $fill x $desc_size;
364ba813f7cSMauro Carvalho Chehab	print "+";
365dbb90902SMauro Carvalho Chehab	print $ln_marker x $status_size;
366ba813f7cSMauro Carvalho Chehab	print "+\n";
36752a4be3fSMauro Carvalho Chehab}
36852a4be3fSMauro Carvalho Chehab
36952a4be3fSMauro Carvalho Chehabsub output_matrix {
370ba813f7cSMauro Carvalho Chehab	my $title = "Feature status on all architectures";
371*f5889e70SMauro Carvalho Chehab	my $notcompat = "Not compatible";
37252a4be3fSMauro Carvalho Chehab
37352a4be3fSMauro Carvalho Chehab	print "=" x length($title) . "\n";
37452a4be3fSMauro Carvalho Chehab	print "$title\n";
37552a4be3fSMauro Carvalho Chehab	print "=" x length($title) . "\n\n";
37652a4be3fSMauro Carvalho Chehab
377dbb90902SMauro Carvalho Chehab	my $desc_title = "$h_kconfig / $h_description";
378dbb90902SMauro Carvalho Chehab
379dbb90902SMauro Carvalho Chehab	my $desc_size = $max_size_kconfig + 4;
380*f5889e70SMauro Carvalho Chehab	if (!$description_size) {
381dbb90902SMauro Carvalho Chehab		$desc_size = $max_size_description if ($max_size_description > $desc_size);
382*f5889e70SMauro Carvalho Chehab	} else {
383*f5889e70SMauro Carvalho Chehab		$desc_size = $description_size if ($description_size > $desc_size);
384*f5889e70SMauro Carvalho Chehab	}
385*f5889e70SMauro Carvalho Chehab	$desc_size = $max_description_word if ($max_description_word > $desc_size);
386*f5889e70SMauro Carvalho Chehab
387dbb90902SMauro Carvalho Chehab	$desc_size = length($desc_title) if (length($desc_title) > $desc_size);
388dbb90902SMauro Carvalho Chehab
389*f5889e70SMauro Carvalho Chehab	$max_size_status = length($notcompat) if (length($notcompat) > $max_size_status);
390*f5889e70SMauro Carvalho Chehab
391*f5889e70SMauro Carvalho Chehab	# Ensure that the status will fit
392*f5889e70SMauro Carvalho Chehab	my $min_status_size = $max_size_status + $max_size_arch + 6;
393*f5889e70SMauro Carvalho Chehab	$status_size = $min_status_size if ($status_size < $min_status_size);
394*f5889e70SMauro Carvalho Chehab
395dbb90902SMauro Carvalho Chehab
396ba813f7cSMauro Carvalho Chehab	my $cur_subsys = "";
39752a4be3fSMauro Carvalho Chehab	foreach my $name (sort {
398ba813f7cSMauro Carvalho Chehab				($data{$a}->{subsys} cmp $data{$b}->{subsys}) or
399ca908577SMauro Carvalho Chehab				("\L$a" cmp "\L$b")
40052a4be3fSMauro Carvalho Chehab			       } keys %data) {
401ba813f7cSMauro Carvalho Chehab
402ba813f7cSMauro Carvalho Chehab		if ($cur_subsys ne $data{$name}->{subsys}) {
403ba813f7cSMauro Carvalho Chehab			if ($cur_subsys ne "") {
404ba813f7cSMauro Carvalho Chehab				printf "\n";
405ba813f7cSMauro Carvalho Chehab			}
406ba813f7cSMauro Carvalho Chehab
407ba813f7cSMauro Carvalho Chehab			$cur_subsys = $data{$name}->{subsys};
408ba813f7cSMauro Carvalho Chehab
409ba813f7cSMauro Carvalho Chehab			my $title = "Subsystem: $cur_subsys";
410ba813f7cSMauro Carvalho Chehab			print "$title\n";
411ba813f7cSMauro Carvalho Chehab			print "=" x length($title) . "\n\n";
412ba813f7cSMauro Carvalho Chehab
413dbb90902SMauro Carvalho Chehab
414dbb90902SMauro Carvalho Chehab			matrix_lines($desc_size, $status_size, 0);
415dbb90902SMauro Carvalho Chehab
416ba813f7cSMauro Carvalho Chehab			printf "|%-${max_size_name}s", $h_name;
417dbb90902SMauro Carvalho Chehab			printf "|%-${desc_size}s", $desc_title;
418ba813f7cSMauro Carvalho Chehab
419dbb90902SMauro Carvalho Chehab			printf "|%-${status_size}s|\n", "Status per architecture";
420dbb90902SMauro Carvalho Chehab			matrix_lines($desc_size, $status_size, 1);
421ba813f7cSMauro Carvalho Chehab		}
42252a4be3fSMauro Carvalho Chehab
42352a4be3fSMauro Carvalho Chehab		my %arch_table = %{$data{$name}->{table}};
424dbb90902SMauro Carvalho Chehab		my $cur_status = "";
42552a4be3fSMauro Carvalho Chehab
426*f5889e70SMauro Carvalho Chehab		my (@lines, @descs);
427dbb90902SMauro Carvalho Chehab		my $line = "";
428dbb90902SMauro Carvalho Chehab		foreach my $arch (sort {
4294fa32f87SMauro Carvalho Chehab					($arch_table{$b} cmp $arch_table{$a}) or
430dbb90902SMauro Carvalho Chehab					("\L$a" cmp "\L$b")
431dbb90902SMauro Carvalho Chehab				       } keys %arch_table) {
432dbb90902SMauro Carvalho Chehab
433dbb90902SMauro Carvalho Chehab			my $status = $arch_table{$arch};
434dbb90902SMauro Carvalho Chehab
435dbb90902SMauro Carvalho Chehab			if ($status eq "---") {
436*f5889e70SMauro Carvalho Chehab				$status = $notcompat;
437dbb90902SMauro Carvalho Chehab			}
438dbb90902SMauro Carvalho Chehab
439dbb90902SMauro Carvalho Chehab			if ($status ne $cur_status) {
440dbb90902SMauro Carvalho Chehab				if ($line ne "") {
441dbb90902SMauro Carvalho Chehab					push @lines, $line;
442dbb90902SMauro Carvalho Chehab					$line = "";
443dbb90902SMauro Carvalho Chehab				}
444dbb90902SMauro Carvalho Chehab				$line = "- **" . $status . "**: " . $arch;
445dbb90902SMauro Carvalho Chehab			} elsif (length($line) + length ($arch) + 2 < $status_size) {
446dbb90902SMauro Carvalho Chehab				$line .= ", " . $arch;
447dbb90902SMauro Carvalho Chehab			} else {
448dbb90902SMauro Carvalho Chehab				push @lines, $line;
449dbb90902SMauro Carvalho Chehab				$line = "  " . $arch;
450dbb90902SMauro Carvalho Chehab			}
451dbb90902SMauro Carvalho Chehab			$cur_status = $status;
452dbb90902SMauro Carvalho Chehab		}
453dbb90902SMauro Carvalho Chehab		push @lines, $line if ($line ne "");
454dbb90902SMauro Carvalho Chehab
455*f5889e70SMauro Carvalho Chehab		my $description = $data{$name}->{description};
456*f5889e70SMauro Carvalho Chehab		while (length($description) > $desc_size) {
457*f5889e70SMauro Carvalho Chehab			my $d = substr $description, 0, $desc_size;
458*f5889e70SMauro Carvalho Chehab
459*f5889e70SMauro Carvalho Chehab			# Ensure that it will end on a space
460*f5889e70SMauro Carvalho Chehab			# if it can't, it means that the size is too small
461*f5889e70SMauro Carvalho Chehab			# Instead of aborting it, let's print what we have
462*f5889e70SMauro Carvalho Chehab			if (!($d =~ s/^(.*)\s+.*/$1/)) {
463*f5889e70SMauro Carvalho Chehab				$d = substr $d, 0, -1;
464*f5889e70SMauro Carvalho Chehab				push @descs, "$d\\";
465*f5889e70SMauro Carvalho Chehab				$description =~ s/^\Q$d\E//;
466*f5889e70SMauro Carvalho Chehab			} else {
467*f5889e70SMauro Carvalho Chehab				push @descs, $d;
468*f5889e70SMauro Carvalho Chehab				$description =~ s/^\Q$d\E\s+//;
469*f5889e70SMauro Carvalho Chehab			}
470*f5889e70SMauro Carvalho Chehab		}
471*f5889e70SMauro Carvalho Chehab		push @descs, $description;
472*f5889e70SMauro Carvalho Chehab
473*f5889e70SMauro Carvalho Chehab		# Ensure that the full description will be printed
474*f5889e70SMauro Carvalho Chehab		push @lines, "" while (scalar(@lines) < 2 + scalar(@descs));
475dbb90902SMauro Carvalho Chehab
476dbb90902SMauro Carvalho Chehab		my $ln = 0;
477dbb90902SMauro Carvalho Chehab		for my $line(@lines) {
478dbb90902SMauro Carvalho Chehab			if (!$ln) {
479dbb90902SMauro Carvalho Chehab				printf "|%-${max_size_name}s", $name;
480dbb90902SMauro Carvalho Chehab				printf "|%-${desc_size}s", "``" . $data{$name}->{kconfig} . "``";
481*f5889e70SMauro Carvalho Chehab			} elsif ($ln >= 2 && scalar(@descs)) {
482ba813f7cSMauro Carvalho Chehab				printf "|%-${max_size_name}s", "";
483*f5889e70SMauro Carvalho Chehab				printf "|%-${desc_size}s", shift @descs;
484dbb90902SMauro Carvalho Chehab			} else {
485dbb90902SMauro Carvalho Chehab				printf "|%-${max_size_name}s", "";
486dbb90902SMauro Carvalho Chehab				printf "|%-${desc_size}s", "";
48752a4be3fSMauro Carvalho Chehab			}
488dbb90902SMauro Carvalho Chehab
489dbb90902SMauro Carvalho Chehab			printf "|%-${status_size}s|\n", $line;
490dbb90902SMauro Carvalho Chehab
491dbb90902SMauro Carvalho Chehab			$ln++;
49252a4be3fSMauro Carvalho Chehab		}
493dbb90902SMauro Carvalho Chehab		matrix_lines($desc_size, $status_size, 0);
494ba813f7cSMauro Carvalho Chehab	}
49552a4be3fSMauro Carvalho Chehab}
49652a4be3fSMauro Carvalho Chehab
49752a4be3fSMauro Carvalho Chehab
49852a4be3fSMauro Carvalho Chehab#
49952a4be3fSMauro Carvalho Chehab# Parses all feature files located at $prefix dir
50052a4be3fSMauro Carvalho Chehab#
50152a4be3fSMauro Carvalho Chehabfind({wanted =>\&parse_feat, no_chdir => 1}, $prefix);
50252a4be3fSMauro Carvalho Chehab
50352a4be3fSMauro Carvalho Chehabprint STDERR Data::Dumper->Dump([\%data], [qw(*data)]) if ($debug);
50452a4be3fSMauro Carvalho Chehab
50552a4be3fSMauro Carvalho Chehab#
50652a4be3fSMauro Carvalho Chehab# Handles the command
50752a4be3fSMauro Carvalho Chehab#
50852a4be3fSMauro Carvalho Chehabif ($cmd eq "current") {
50952a4be3fSMauro Carvalho Chehab	$arch = qx(uname -m | sed 's/x86_64/x86/' | sed 's/i386/x86/');
51052a4be3fSMauro Carvalho Chehab	$arch =~s/\s+$//;
51152a4be3fSMauro Carvalho Chehab}
51252a4be3fSMauro Carvalho Chehab
513ca908577SMauro Carvalho Chehabif ($cmd eq "ls" or $cmd eq "list") {
514ca908577SMauro Carvalho Chehab	if (!$arch) {
515ca908577SMauro Carvalho Chehab		$arch = qx(uname -m | sed 's/x86_64/x86/' | sed 's/i386/x86/');
516ca908577SMauro Carvalho Chehab		$arch =~s/\s+$//;
517ca908577SMauro Carvalho Chehab	}
518ca908577SMauro Carvalho Chehab
519ca908577SMauro Carvalho Chehab	list_arch_features;
520ca908577SMauro Carvalho Chehab
521ca908577SMauro Carvalho Chehab	exit;
522ca908577SMauro Carvalho Chehab}
523ca908577SMauro Carvalho Chehab
52452a4be3fSMauro Carvalho Chehabif ($cmd ne "validate") {
52552a4be3fSMauro Carvalho Chehab	if ($arch) {
52652a4be3fSMauro Carvalho Chehab		output_arch_table;
52752a4be3fSMauro Carvalho Chehab	} elsif ($feat) {
52852a4be3fSMauro Carvalho Chehab		output_feature;
52952a4be3fSMauro Carvalho Chehab	} else {
53052a4be3fSMauro Carvalho Chehab		output_matrix;
53152a4be3fSMauro Carvalho Chehab	}
53252a4be3fSMauro Carvalho Chehab}
53352a4be3fSMauro Carvalho Chehab
53452a4be3fSMauro Carvalho Chehab__END__
53552a4be3fSMauro Carvalho Chehab
53652a4be3fSMauro Carvalho Chehab=head1 NAME
53752a4be3fSMauro Carvalho Chehab
53852a4be3fSMauro Carvalho Chehabget_feat.pl - parse the Linux Feature files and produce a ReST book.
53952a4be3fSMauro Carvalho Chehab
54052a4be3fSMauro Carvalho Chehab=head1 SYNOPSIS
54152a4be3fSMauro Carvalho Chehab
542ca908577SMauro Carvalho ChehabB<get_feat.pl> [--debug] [--man] [--help] [--dir=<dir>] [--arch=<arch>]
543ca908577SMauro Carvalho Chehab	       [--feature=<feature>|--feat=<feature>] <COMAND> [<ARGUMENT>]
54452a4be3fSMauro Carvalho Chehab
54552a4be3fSMauro Carvalho ChehabWhere <COMMAND> can be:
54652a4be3fSMauro Carvalho Chehab
54752a4be3fSMauro Carvalho Chehab=over 8
54852a4be3fSMauro Carvalho Chehab
549ca908577SMauro Carvalho ChehabB<current>               - output table in ReST compatible ASCII format
550ca908577SMauro Carvalho Chehab			   with features for this machine's architecture
55152a4be3fSMauro Carvalho Chehab
552ca908577SMauro Carvalho ChehabB<rest>                  - output table(s)  in ReST compatible ASCII format
553ca908577SMauro Carvalho Chehab			   with features in ReST markup language. The output
554ca908577SMauro Carvalho Chehab			   is affected by --arch or --feat/--feature flags.
55552a4be3fSMauro Carvalho Chehab
556ca908577SMauro Carvalho ChehabB<validate>              - validate the contents of the files under
557ca908577SMauro Carvalho Chehab			   Documentation/features.
558ca908577SMauro Carvalho Chehab
559ca908577SMauro Carvalho ChehabB<ls> or B<list>         - list features for this machine's architecture,
560ca908577SMauro Carvalho Chehab			   using an easier to parse format.
561ca908577SMauro Carvalho Chehab			   The output is affected by --arch flag.
56252a4be3fSMauro Carvalho Chehab
56352a4be3fSMauro Carvalho Chehab=back
56452a4be3fSMauro Carvalho Chehab
56552a4be3fSMauro Carvalho Chehab=head1 OPTIONS
56652a4be3fSMauro Carvalho Chehab
56752a4be3fSMauro Carvalho Chehab=over 8
56852a4be3fSMauro Carvalho Chehab
56952a4be3fSMauro Carvalho Chehab=item B<--arch>
57052a4be3fSMauro Carvalho Chehab
57152a4be3fSMauro Carvalho ChehabOutput features for an specific architecture, optionally filtering for
57252a4be3fSMauro Carvalho Chehaba single specific feature.
57352a4be3fSMauro Carvalho Chehab
574ca908577SMauro Carvalho Chehab=item B<--feat> or B<--feature>
57552a4be3fSMauro Carvalho Chehab
576ca908577SMauro Carvalho ChehabOutput features for a single specific feature.
57752a4be3fSMauro Carvalho Chehab
57852a4be3fSMauro Carvalho Chehab=item B<--dir>
57952a4be3fSMauro Carvalho Chehab
58052a4be3fSMauro Carvalho ChehabChanges the location of the Feature files. By default, it uses
58152a4be3fSMauro Carvalho Chehabthe Documentation/features directory.
58252a4be3fSMauro Carvalho Chehab
58352a4be3fSMauro Carvalho Chehab=item B<--debug>
58452a4be3fSMauro Carvalho Chehab
58552a4be3fSMauro Carvalho ChehabPut the script in verbose mode, useful for debugging. Can be called multiple
58652a4be3fSMauro Carvalho Chehabtimes, to increase verbosity.
58752a4be3fSMauro Carvalho Chehab
58852a4be3fSMauro Carvalho Chehab=item B<--help>
58952a4be3fSMauro Carvalho Chehab
59052a4be3fSMauro Carvalho ChehabPrints a brief help message and exits.
59152a4be3fSMauro Carvalho Chehab
59252a4be3fSMauro Carvalho Chehab=item B<--man>
59352a4be3fSMauro Carvalho Chehab
59452a4be3fSMauro Carvalho ChehabPrints the manual page and exits.
59552a4be3fSMauro Carvalho Chehab
59652a4be3fSMauro Carvalho Chehab=back
59752a4be3fSMauro Carvalho Chehab
59852a4be3fSMauro Carvalho Chehab=head1 DESCRIPTION
59952a4be3fSMauro Carvalho Chehab
60052a4be3fSMauro Carvalho ChehabParse the Linux feature files from Documentation/features (by default),
60152a4be3fSMauro Carvalho Chehaboptionally producing results at ReST format.
60252a4be3fSMauro Carvalho Chehab
60352a4be3fSMauro Carvalho ChehabIt supports output data per architecture, per feature or a
60452a4be3fSMauro Carvalho Chehabfeature x arch matrix.
60552a4be3fSMauro Carvalho Chehab
60652a4be3fSMauro Carvalho ChehabWhen used with B<rest> command, it will use either one of the tree formats:
60752a4be3fSMauro Carvalho Chehab
60852a4be3fSMauro Carvalho ChehabIf neither B<--arch> or B<--feature> arguments are used, it will output a
60952a4be3fSMauro Carvalho Chehabmatrix with features per architecture.
61052a4be3fSMauro Carvalho Chehab
61152a4be3fSMauro Carvalho ChehabIf B<--arch> argument is used, it will output the features availability for
61252a4be3fSMauro Carvalho Chehaba given architecture.
61352a4be3fSMauro Carvalho Chehab
61452a4be3fSMauro Carvalho ChehabIf B<--feat> argument is used, it will output the content of the feature
61552a4be3fSMauro Carvalho Chehabfile using ReStructured Text markup.
61652a4be3fSMauro Carvalho Chehab
61752a4be3fSMauro Carvalho Chehab=head1 BUGS
61852a4be3fSMauro Carvalho Chehab
61952a4be3fSMauro Carvalho ChehabReport bugs to Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
62052a4be3fSMauro Carvalho Chehab
62152a4be3fSMauro Carvalho Chehab=head1 COPYRIGHT
62252a4be3fSMauro Carvalho Chehab
62352a4be3fSMauro Carvalho ChehabCopyright (c) 2019 by Mauro Carvalho Chehab <mchehab+samsung@kernel.org>.
62452a4be3fSMauro Carvalho Chehab
62552a4be3fSMauro Carvalho ChehabLicense GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>.
62652a4be3fSMauro Carvalho Chehab
62752a4be3fSMauro Carvalho ChehabThis is free software: you are free to change and redistribute it.
62852a4be3fSMauro Carvalho ChehabThere is NO WARRANTY, to the extent permitted by law.
62952a4be3fSMauro Carvalho Chehab
63052a4be3fSMauro Carvalho Chehab=cut
631