+#!/usr/bin/perl
+use strict;
+my %package;
+my %category;
+
+sub parse_target_metadata() {
+ my ($target, @target, $profile);
+ while (<>) {
+ chomp;
+ /^Target:\s*((.+)-(\d+\.\d+))\s*$/ and do {
+ my $conf = uc $3.'_'.$2;
+ $conf =~ tr/\.-/__/;
+ $target = {
+ id => $1,
+ conf => $conf,
+ board => $2,
+ kernel => $3,
+ profiles => []
+ };
+ push @target, $target;
+ };
+ /^Target-Name:\s*(.+)\s*$/ and $target->{name} = $1;
+ /^Target-Path:\s*(.+)\s*$/ and $target->{path} = $1;
+ /^Target-Arch:\s*(.+)\s*$/ and $target->{arch} = $1;
+ /^Target-Features:\s*(.+)\s*$/ and $target->{features} = [ split(/\s+/, $1) ];
+ /^Target-Description:/ and do {
+ my $desc;
+ while (<>) {
+ last if /^@@/;
+ $desc .= $_;
+ }
+ $target->{desc} = $desc;
+ };
+ /^Linux-Version:\s*(.+)\s*$/ and $target->{version} = $1;
+ /^Linux-Release:\s*(.+)\s*$/ and $target->{release} = $1;
+ /^Linux-Kernel-Arch:\s*(.+)\s*$/ and $target->{karch} = $1;
+ /^Default-Packages:\s*(.+)\s*$/ and $target->{packages} = [ split(/\s+/, $1) ];
+ /^Target-Profile:\s*(.+)\s*$/ and do {
+ $profile = {
+ id => $1,
+ name => $1,
+ packages => []
+ };
+ push @{$target->{profiles}}, $profile;
+ };
+ /^Target-Profile-Name:\s*(.+)\s*$/ and $profile->{name} = $1;
+ /^Target-Profile-Packages:\s*(.*)\s*$/ and $profile->{packages} = [ split(/\s+/, $1) ];
+ }
+ return @target;
+}
+
+sub parse_package_metadata() {
+ my $pkg;
+ my $makefile;
+ my $src;
+ while (<>) {
+ chomp;
+ /^Source-Makefile: \s*(.+\/([^\/]+)\/Makefile)\s*$/ and do {
+ $makefile = $1;
+ $src = $2;
+ undef $pkg;
+ };
+ /^Package: \s*(.+)\s*$/ and do {
+ $pkg = {};
+ $pkg->{src} = $src;
+ $pkg->{makefile} = $makefile;
+ $pkg->{name} = $1;
+ $pkg->{default} = "m if ALL";
+ $package{$1} = $pkg;
+ };
+ /^Version: \s*(.+)\s*$/ and $pkg->{version} = $1;
+ /^Title: \s*(.+)\s*$/ and $pkg->{title} = $1;
+ /^Menu: \s*(.+)\s*$/ and $pkg->{menu} = $1;
+ /^Submenu: \s*(.+)\s*$/ and $pkg->{submenu} = $1;
+ /^Submenu-Depends: \s*(.+)\s*$/ and $pkg->{submenudep} = $1;
+ /^Default: \s*(.+)\s*$/ and $pkg->{default} = $1;
+ /^Provides: \s*(.+)\s*$/ and do {
+ my @vpkg = split /\s+/, $1;
+ foreach my $vpkg (@vpkg) {
+ $package{$vpkg} or $package{$vpkg} = { vdepends => [] };
+ push @{$package{$vpkg}->{vdepends}}, $pkg->{name};
+ }
+ };
+ /^Depends: \s*(.+)\s*$/ and do {
+ my @dep = split /\s+/, $1;
+ $pkg->{depends} = \@dep;
+ };
+ /^Category: \s*(.+)\s*$/ and do {
+ $pkg->{category} = $1;
+ defined $category{$1} or $category{$1} = {};
+ defined $category{$1}->{$src} or $category{$1}->{$src} = [];
+ push @{$category{$1}->{$src}}, $pkg;
+ };
+ /^Description: \s*(.*)\s*$/ and do {
+ my $desc = "\t\t$1\n\n";
+ my $line;
+ while ($line = <>) {
+ last if $line =~ /^@@/;
+ $desc .= "\t\t$line";
+ }
+ $pkg->{description} = $desc;
+ };
+ /^Config: \s*(.*)\s*$/ and do {
+ my $conf = "$1\n";
+ my $line;
+ while ($line = <>) {
+ last if $line =~ /^@@/;
+ $conf .= "$line";
+ }
+ $pkg->{config} = $conf;
+ }
+ }
+ return %category;
+}
+
+
+sub gen_target_mk() {
+ my @target = parse_target_metadata();
+
+ @target = sort {
+ $a->{id} cmp $b->{id}
+ } @target;
+
+ foreach my $target (@target) {
+ my ($profiles_def, $profiles_eval);
+ my $conf = uc $target->{kernel}.'_'.$target->{board};
+ $conf =~ tr/\.-/__/;
+
+ foreach my $profile (@{$target->{profiles}}) {
+ $profiles_def .= "
+ define Profile/$conf\_$profile->{id}
+ ID:=$profile->{id}
+ NAME:=$profile->{name}
+ PACKAGES:=".join(" ", @{$profile->{packages}})."
+ endef";
+ $profiles_eval .= "
+\$(eval \$(call Profile,$conf\_$profile->{id}))"
+ }
+ print "
+ifeq (\$(CONFIG_LINUX_$conf),y)
+ define Target
+ KERNEL:=$target->{kernel}
+ BOARD:=$target->{board}
+ BOARDNAME:=$target->{name}
+ LINUX_VERSION:=$target->{version}
+ LINUX_RELEASE:=$target->{release}
+ LINUX_KARCH:=$target->{karch}
+ DEFAULT_PACKAGES:=".join(" ", @{$target->{packages}})."
+ endef$profiles_def
+endif$profiles_eval
+
+"
+ }
+ print "\$(eval \$(call Target))\n";
+}
+
+sub target_config_features(@) {
+ my $ret;
+
+ while ($_ = shift @_) {
+ /broken/ and $ret .= "\tdepends BROKEN\n";
+ /pci/ and $ret .= "\tselect PCI_SUPPORT\n";
+ /usb/ and $ret .= "\tselect USB_SUPPORT\n";
+ /atm/ and $ret .= "\tselect ATM_SUPPORT\n";
+ /pcmcia/ and $ret .= "\tselect PCMCIA_SUPPORT\n";
+ /squashfs/ and $ret .= "\tselect USES_SQUASHFS\n";
+ /jffs2/ and $ret .= "\tselect USES_JFFS2\n";
+ /ext2/ and $ret .= "\tselect USES_EXT2\n";
+ }
+ return $ret;
+}
+
+
+sub gen_target_config() {
+ my @target = parse_target_metadata();
+
+ @target = sort {
+ $a->{name} cmp $b->{name}
+ } @target;
+
+
+ print <<EOF;
+choice
+ prompt "Target System"
+ default LINUX_2_4_BRCM
+
+EOF
+
+ foreach my $target (@target) {
+ my $features = target_config_features(@{$target->{features}});
+ my $help = $target->{desc};
+ my $kernel = $target->{kernel};
+ $kernel =~ tr/./_/;
+
+ chomp $features;
+ $features .= "\n";
+ if ($help =~ /\w+/) {
+ $help =~ s/^\s*/\t /mg;
+ $help = "\thelp\n$help";
+ } else {
+ undef $help;
+ }
+
+ print <<EOF
+config LINUX_$target->{conf}
+ bool "$target->{name}"
+ select $target->{arch}
+ select LINUX_$kernel
+$features$help
+
+EOF
+ }
+
+ print <<EOF;
+if DEVEL
+
+config LINUX_2_6_ARM
+ bool "UNSUPPORTED little-endian arm platform"
+ depends BROKEN
+ select LINUX_2_6
+ select arm
+
+config LINUX_2_6_CRIS
+ bool "UNSUPPORTED cris platform"
+ depends BROKEN
+ select LINUX_2_6
+ select cris
+
+config LINUX_2_6_M68K
+ bool "UNSUPPORTED m68k platform"
+ depends BROKEN
+ select LINUX_2_6
+ select m68k
+
+config LINUX_2_6_SH3
+ bool "UNSUPPORTED little-endian sh3 platform"
+ depends BROKEN
+ select LINUX_2_6
+ select sh3
+
+config LINUX_2_6_SH3EB
+ bool "UNSUPPORTED big-endian sh3 platform"
+ depends BROKEN
+ select LINUX_2_6
+ select sh3eb
+
+config LINUX_2_6_SH4
+ bool "UNSUPPORTED little-endian sh4 platform"
+ depends BROKEN
+ select LINUX_2_6
+ select sh4
+
+config LINUX_2_6_SH4EB
+ bool "UNSUPPORTED big-endian sh4 platform"
+ depends BROKEN
+ select LINUX_2_6
+ select sh4eb
+
+config LINUX_2_6_SPARC
+ bool "UNSUPPORTED sparc platform"
+ depends BROKEN
+ select LINUX_2_6
+ select sparc
+
+endif
+
+endchoice
+
+choice
+ prompt "Target Profile"
+
+EOF
+
+ foreach my $target (@target) {
+ my $profiles = $target->{profiles};
+
+ @$profiles > 0 or $profiles = [
+ {
+ id => 'Default',
+ name => 'Default',
+ packages => []
+ }
+ ];
+ foreach my $profile (@$profiles) {
+ print <<EOF;
+config LINUX_$target->{conf}_$profile->{id}
+ bool "$profile->{name}"
+ depends LINUX_$target->{conf}
+EOF
+ foreach my $pkg (@{$target->{packages}}, @{$profile->{packages}}) {
+ print "\tselect DEFAULT_$pkg\n";
+ }
+ print "\n";
+ }
+ }
+
+ print "endchoice\n";
+}
+
+sub find_package_dep($$) {
+ my $pkg = shift;
+ my $name = shift;
+ my $deps = ($pkg->{vdepends} or $pkg->{depends});
+
+ return 0 unless defined $deps;
+ foreach my $dep (@{$deps}) {
+ return 1 if $dep eq $name;
+ return 1 if ($package{$dep} and (find_package_dep($package{$dep},$name) == 1));
+ }
+ return 0;
+}
+
+sub package_depends($$) {
+ my $a = shift;
+ my $b = shift;
+ my $ret;
+
+ return 0 if ($a->{submenu} ne $b->{submenu});
+ if (find_package_dep($a, $b->{name}) == 1) {
+ $ret = 1;
+ } elsif (find_package_dep($b, $a->{name}) == 1) {
+ $ret = -1;
+ } else {
+ return 0;
+ }
+ return $ret;
+}
+
+sub print_package_config_category($) {
+ my $cat = shift;
+ my %menus;
+ my %menu_dep;
+
+ return unless $category{$cat};
+
+ print "menu \"$cat\"\n\n";
+ my %spkg = %{$category{$cat}};
+
+ foreach my $spkg (sort {uc($a) cmp uc($b)} keys %spkg) {
+ foreach my $pkg (@{$spkg{$spkg}}) {
+ my $menu = $pkg->{submenu};
+ if ($menu) {
+ $menu_dep{$menu} or $menu_dep{$menu} = $pkg->{submenudep};
+ } else {
+ $menu = 'undef';
+ }
+ $menus{$menu} or $menus{$menu} = [];
+ push @{$menus{$menu}}, $pkg;
+ print "\tconfig DEFAULT_".$pkg->{name}."\n";
+ print "\t\tbool\n\n";
+ }
+ }
+ my @menus = sort {
+ ($a eq 'undef' ? 1 : 0) or
+ ($b eq 'undef' ? -1 : 0) or
+ ($a cmp $b)
+ } keys %menus;
+
+ foreach my $menu (@menus) {
+ my @pkgs = sort {
+ package_depends($a, $b) or
+ ($a->{name} cmp $b->{name})
+ } @{$menus{$menu}};
+ if ($menu ne 'undef') {
+ $menu_dep{$menu} and print "if $menu_dep{$menu}\n";
+ print "menu \"$menu\"\n";
+ }
+ foreach my $pkg (@pkgs) {
+ my $title = $pkg->{name};
+ my $c = (72 - length($pkg->{name}) - length($pkg->{title}));
+ if ($c > 0) {
+ $title .= ("." x $c). " ". $pkg->{title};
+ }
+ print "\t";
+ $pkg->{menu} and print "menu";
+ print "config PACKAGE_".$pkg->{name}."\n";
+ print "\t\ttristate \"$title\"\n";
+ print "\t\tdefault y if DEFAULT_".$pkg->{name}."\n";
+ foreach my $default (split /\s*,\s*/, $pkg->{default}) {
+ print "\t\tdefault $default\n";
+ }
+ foreach my $depend (@{$pkg->{depends}}) {
+ my $m = "depends";
+ $depend =~ s/^([@\+]+)//;
+ my $flags = $1;
+ my $vdep;
+
+ if ($vdep = $package{$depend}->{vdepends}) {
+ $depend = join("||", map { "PACKAGE_".$_ } @$vdep);
+ } else {
+ $flags =~ /@/ or $depend = "PACKAGE_$depend";
+ $flags =~ /\+/ and $m = "select";
+ }
+ print "\t\t$m $depend\n";
+ }
+ print "\t\thelp\n";
+ print $pkg->{description};
+ print "\n";
+
+ $pkg->{config} and print $pkg->{config}."\n";
+ }
+ if ($menu ne 'undef') {
+ print "endmenu\n";
+ $menu_dep{$menu} and print "endif\n";
+ }
+ }
+ print "endmenu\n\n";
+
+ undef $category{$cat};
+}
+
+sub gen_package_config() {
+ parse_package_metadata();
+ print_package_config_category 'Base system';
+ foreach my $cat (keys %category) {
+ print_package_config_category $cat;
+ }
+}
+
+sub parse_command() {
+ my $cmd = shift @ARGV;
+ for ($cmd) {
+ /^target_mk$/ and return gen_target_mk();
+ /^target_config$/ and return gen_target_config();
+ /^package_config$/ and return gen_package_config();
+ }
+ print <<EOF
+Available Commands:
+ $0 target_mk [file] Target metadata in makefile format
+ $0 target_config [file] Target metadata in Kconfig format
+ $0 package_config [file] Package metadata in Kconfig format
+EOF
+}
+
+parse_command();