menuconfig: include dependency checking in submenu sorting function
[openwrt.git] / scripts / gen_menuconfig.pl
1 #!/usr/bin/perl
2
3 # Copyright (C) 2006 OpenWrt.org
4 #
5 # This is free software, licensed under the GNU General Public License v2.
6 # See /LICENSE for more information.
7 #
8
9 use strict;
10
11 my $src;
12 my $makefile;
13 my $pkg;
14 my %package;
15 my %category;
16 my $cur_menu;
17 my $cur_menu_dep;
18
19 sub close_submenu {
20         if ($cur_menu) {
21                 print "endmenu\n";
22                 $cur_menu_dep and do {
23                         print "endif\n";
24                         $cur_menu_dep = undef;
25                 };
26                 undef $cur_menu;
27         } 
28 }
29
30 sub find_dep($$) {
31         my $pkg = shift;
32         my $name = shift;
33         
34         return 0 unless defined $pkg->{depends};
35         foreach my $dep (@{$pkg->{depends}}) {
36                 return 1 if $dep eq $name;
37                 return 1 if ($package{$dep} and (find_dep($package{$dep},$name) == 1));
38         }
39         return 0;
40 }
41
42 sub depends($$) {
43         my $a = shift;
44         my $b = shift;
45         my $ret;
46         
47         if (find_dep($a, $b->{name}) == 1) {
48                 $ret = 1;
49         } elsif (find_dep($b, $a->{name}) == 1) {
50                 $ret = -1;
51         } else {
52                 $ret = 0;
53         }
54 #       print STDERR "depends($a->{name}, $b->{name}) == $ret\n";
55         return $ret;
56 }
57
58
59 sub print_category($) {
60         my $cat = shift;
61         
62         return unless $category{$cat};
63         
64         print "menu \"$cat\"\n\n";
65         my %spkg = %{$category{$cat}};
66         foreach my $spkg (sort {uc($a) cmp uc($b)} keys %spkg) {
67                 my @pkgs = sort {
68                         depends($a, $b) or
69                         $a->{submenu}."->".$a->{name} cmp $b->{submenu}."->".$b->{name}
70                 } @{$spkg{$spkg}};
71                 foreach my $pkg (@pkgs) {
72                         if ($cur_menu ne $pkg->{submenu}) {
73                                 close_submenu();
74                                 if ($pkg->{submenu}) {
75                                         $cur_menu = $pkg->{submenu};
76                                         $cur_menu_dep = $pkg->{submenudep} and print "if $cur_menu_dep\n";
77                                         print "menu \"$cur_menu\"\n";
78                                 }
79                         }
80                         my $title = $pkg->{name};
81                         my $c = (72 - length($pkg->{name}) - length($pkg->{title}));
82                         if ($c > 0) {
83                                 $title .= ("." x $c). " ". $pkg->{title};
84                         }
85                         print "\t";
86                         $pkg->{menu} and print "menu";
87                         print "config PACKAGE_".$pkg->{name}."\n";
88                         print "\t\ttristate \"$title\"\n";
89                         foreach my $default (split /\s*,\s*/, $pkg->{default}) {
90                                 print "\t\tdefault $default\n";
91                         }
92                         foreach my $depend (@{$pkg->{depends}}) {
93                                 my $m = "depends";
94                                 $depend =~ s/^([@\+]+)//;
95                                 my $flags = $1;
96                                 $flags =~ /@/ or $depend = "PACKAGE_$depend";
97                                 $flags =~ /\+/ and $m = "select";
98                                 print "\t\t$m $depend\n";
99                         }
100                         print "\t\thelp\n";
101                         print $pkg->{description};
102                         print "\n";
103
104                         $pkg->{config} and print $pkg->{config}."\n";
105                 }
106         }
107         close_submenu();
108         print "endmenu\n\n";
109         
110         undef $category{$cat};
111 }
112
113 my $line;
114 while ($line = <>) {
115         chomp $line;
116         $line =~ /^Source-Makefile: \s*(.+\/([^\/]+)\/Makefile)\s*$/ and do {
117                 $makefile = $1;
118                 $src = $2;
119                 undef $pkg;
120         };
121         $line =~ /^Package: \s*(.+)\s*$/ and do {
122                 $pkg = {};
123                 $pkg->{src} = $src;
124                 $pkg->{makefile} = $makefile;
125                 $pkg->{name} = $1;
126                 $pkg->{default} = "m if ALL";
127                 $package{$1} = $pkg;
128         };
129         $line =~ /^Version: \s*(.+)\s*$/ and $pkg->{version} = $1;
130         $line =~ /^Title: \s*(.+)\s*$/ and $pkg->{title} = $1;
131         $line =~ /^Menu: \s*(.+)\s*$/ and $pkg->{menu} = $1;
132         $line =~ /^Submenu: \s*(.+)\s*$/ and $pkg->{submenu} = $1;
133         $line =~ /^Submenu-Depends: \s*(.+)\s*$/ and $pkg->{submenudep} = $1;
134         $line =~ /^Default: \s*(.+)\s*$/ and $pkg->{default} = $1;
135         $line =~ /^Depends: \s*(.+)\s*$/ and do {
136                 my @dep = split /\s+/, $1;
137                 $pkg->{depends} = \@dep;
138         };
139         $line =~ /^Category: \s*(.+)\s*$/ and do {
140                 $pkg->{category} = $1;
141                 defined $category{$1} or $category{$1} = {};
142                 defined $category{$1}->{$src} or $category{$1}->{$src} = [];
143                 push @{$category{$1}->{$src}}, $pkg;
144         };
145         $line =~ /^Description: \s*(.*)\s*$/ and do {
146                 my $desc = "\t\t$1\n\n";
147                 my $line;
148                 while ($line = <>) {
149                         last if $line =~ /^@@/;
150                         $desc .= "\t\t$line";
151                 }
152                 $pkg->{description} = $desc;
153         };
154         $line =~ /^Config: \s*(.*)\s*$/ and do {
155                 my $conf = "$1\n";
156                 my $line;
157                 while ($line = <>) {
158                         last if $line =~ /^@@/;
159                         $conf .= "$line";
160                 }
161                 $pkg->{config} = $conf;
162         }
163 }
164
165 print_category 'Base system';
166 foreach my $cat (keys %category) {
167         print_category $cat;
168 }