#!/usr/bin/perl
use strict;
use daveperl;

my %flags;

sub build_dir
{
	my $release = `uname -r`;
	chomp $release;
	return "/lib/modules/$release/build/";
}

sub include_file
{
	my $file = shift;
	return build_dir().$file;
}

sub gfpflags
{
	my @lines = cat_file_into_array(include_file("include/linux/gfp.h"));
	die "not enough lines 1" if scalar(@lines) < 5;
	@lines = grep(/#define ___GFP_/,@lines);
	die "not enough lines 1" if scalar(@lines) < 5;
	my $hash;
	
	foreach my $line (@lines) {
		dprintf4("gfpflags line: %s", $line);
		$line =~ s#/\*.*\*/##;
		my ($garb, $name, $val) = split(/\s+/, $line, 3);
		$val =~ s/[^x0-9]//g;
		next if $val !~ /^0x/i;
		$hash->{hex $val} = $name;
	}
	return $hash;
}

#doesn't work any more with the enums
sub xxpageflags
{
	my @lines = cat_file_into_array(include_file("include/linux/page-flags.h"));
	die "not enough lines 1" if scalar(@lines) < 5;
	printf "size: %d\n", scalar(@lines);
	@lines = grep(/.define PG_/, @lines);
	printf "size: %d\n", scalar(@lines);
	die "not enough lines 2" if scalar(@lines) < 5;
	my $hash;

	die "not enough lines 3" if scalar(@lines) < 5;

	foreach my $line (@lines) {
		$line =~ s#/\*.*\*/##;
		dprintf4("pageflags line: %s", $line);
		my ($garb, $name, $val) = split(/\s+/, $line, 3);
		$val =~ s/[^0-9]//g;
		#print "val: $val\n";
		#print "name: $name\n";
		#print "hex_val: $hex_val\n";
		$hash->{1<<$val} = $name;
	}
	return $hash;
}

sub bits
{
	my $num = hex shift;
	my @ret;
	my $shifts = 0;
	while ($num != 0) {
		my $set = ($num % 2);
		if ($set) {
			push @ret, (1<<$shifts);
		}
		$num>>=1;
		$shifts++;
	}
	return @ret;
}

sub decode
{
	my $hash = shift();
	my @args = @_;
	foreach my $arg (@args) {

		dprint2 "bits: \n", join("\n", bits($arg))."\n";
		foreach my $bit (bits($arg)) {
			foreach my $key (sort { $a <=> $b} keys %$hash) {
				next if ($key != $bit);
				printf "%08lx - %s\n", $bit, $hash->{$key};
			}
		}
	}
}

decode gfpflags(), @ARGV;
#decode pageflags(), @ARGV;
