2a2511212bb6ac232e47b8a19383a4db4c8b8a29
[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         my $deps = ($pkg->{vdepends} or $pkg->{depends});
34
35         return 0 unless defined $deps;
36         foreach my $dep (@{$deps}) {
37                 return 1 if $dep eq $name;
38                 return 1 if ($package{$dep} and (find_dep($package{$dep},$name) == 1));
39         }
40         return 0;
41 }
42
43 sub depends($$) {
44         my $a = shift;
45         my $b = shift;
46         my $ret;
47
48         if (find_dep($a, $b->{name}) == 1) {
49                 $ret = 1;
50         } elsif (find_dep($b, $a->{name}) == 1) {
51                 $ret = -1;
52         } else {
53                 return 0;
54         }
55 #       print STDERR "depends($a->{name}, $b->{name}) == $ret\n";
56         return $ret;
57 }
58
59
60 sub print_category($) {
61         my $cat = shift;
62         
63         return unless $category{$cat};
64         
65         print "menu \"$cat\"\n\n";
66         my %spkg = %{$category{$cat}};
67         foreach my $spkg (sort {uc($a) cmp uc($b)} keys %spkg) {
68                 my @pkgs = sort {
69                         depends($a, $b) or
70                         $a->{submenu}."->".$a->{name} cmp $b->{submenu}."->".$b->{name}
71                 } @{$spkg{$spkg}};
72                 foreach my $pkg (@pkgs) {
73                         if ($cur_menu ne $pkg->{submenu}) {
74                                 close_submenu();
75                                 if ($pkg->{submenu}) {
76                                         $cur_menu = $pkg->{submenu};
77                                         $cur_menu_dep = $pkg->{submenudep} and print "if $cur_menu_dep\n";
78                                         print "menu \"$cur_menu\"\n";
79                                 }
80                         }
81                         my $title = $pkg->{name};
82                         my $c = (72 - length($pkg->{name}) - length($pkg->{title}));
83                         if ($c > 0) {
84                                 $title .= ("." x $c). " ". $pkg->{title};
85                         }
86                         print "\t";
87                         $pkg->{menu} and print "menu";
88                         print "config PACKAGE_".$pkg->{name}."\n";
89                         print "\t\ttristate \"$title\"\n";
90                         foreach my $default (split /\s*,\s*/, $pkg->{default}) {
91                                 print "\t\tdefault $default\n";
92                         }
93                         foreach my $depend (@{$pkg->{depends}}) {
94                                 my $m = "depends";
95                                 $depend =~ s/^([@\+]+)//;
96                                 my $flags = $1;
97                                 my $vdep;
98                                 
99                                 if ($vdep = $package{$depend}->{vdepends}) {
100                                         $depend = join("||", map { "PACKAGE_".$_ } @$vdep);
101                                 } else {
102                                         $flags =~ /@/ or $depend = "PACKAGE_$depend";
103                                         $flags =~ /\+/ and $m = "select";
104                                 }
105                                 print "\t\t$m $depend\n";
106                         }
107                         print "\t\thelp\n";
108                         print $pkg->{description};
109                         print "\n";
110
111                         $pkg->{config} and print $pkg->{config}."\n";
112                 }
113         }
114         close_submenu();
115         print "endmenu\n\n";
116         
117         undef $category{$cat};
118 }
119
120 my $line;
121 while ($line = <>) {
122         chomp $line;
123         $line =~ /^Source-Makefile: \s*(.+\/([^\/]+)\/Makefile)\s*$/ and do {
124                 $makefile = $1;
125                 $src = $2;
126                 undef $pkg;
127         };
128         $line =~ /^Package: \s*(.+)\s*$/ and do {
129                 $pkg = {};
130                 $pkg->{src} = $src;
131                 $pkg->{makefile} = $makefile;
132                 $pkg->{name} = $1;
133                 $pkg->{default} = "m if ALL";
134                 $package{$1} = $pkg;
135         };
136         $line =~ /^Version: \s*(.+)\s*$/ and $pkg->{version} = $1;
137         $line =~ /^Title: \s*(.+)\s*$/ and $pkg->{title} = $1;
138         $line =~ /^Menu: \s*(.+)\s*$/ and $pkg->{menu} = $1;
139         $line =~ /^Submenu: \s*(.+)\s*$/ and $pkg->{submenu} = $1;
140         $line =~ /^Submenu-Depends: \s*(.+)\s*$/ and $pkg->{submenudep} = $1;
141         $line =~ /^Default: \s*(.+)\s*$/ and $pkg->{default} = $1;
142         $line =~ /^Provides: \s*(.+)\s*$/ and do {
143                 my @vpkg = split /\s+/, $1;
144                 foreach my $vpkg (@vpkg) {
145                         $package{$vpkg} or $package{$vpkg} = { vdepends => [] };
146                         push @{$package{$vpkg}->{vdepends}}, $pkg->{name};
147                 }
148         };
149         $line =~ /^Depends: \s*(.+)\s*$/ and do {
150                 my @dep = split /\s+/, $1;
151                 $pkg->{depends} = \@dep;
152         };
153         $line =~ /^Category: \s*(.+)\s*$/ and do {
154                 $pkg->{category} = $1;
155                 defined $category{$1} or $category{$1} = {};
156                 defined $category{$1}->{$src} or $category{$1}->{$src} = [];
157                 push @{$category{$1}->{$src}}, $pkg;
158         };
159         $line =~ /^Description: \s*(.*)\s*$/ and do {
160                 my $desc = "\t\t$1\n\n";
161                 my $line;
162                 while ($line = <>) {
163                         last if $line =~ /^@@/;
164                         $desc .= "\t\t$line";
165                 }
166                 $pkg->{description} = $desc;
167         };
168         $line =~ /^Config: \s*(.*)\s*$/ and do {
169                 my $conf = "$1\n";
170                 my $line;
171                 while ($line = <>) {
172                         last if $line =~ /^@@/;
173                         $conf .= "$line";
174                 }
175                 $pkg->{config} = $conf;
176         }
177 }
178
179 print_category 'Base system';
180 foreach my $cat (keys %category) {
181         print_category $cat;
182 }