major target cleanup. it is now possible to have subtargets that can override many...
[openwrt.git] / scripts / kconfig.pl
1 #!/usr/bin/env perl
2
3 # Copyright (C) 2006 Felix Fietkau <nbd@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 warnings;
10 use strict;
11
12 my @arg = @ARGV;
13
14 sub load_config($) {
15         my $file = shift;
16         my %config;
17
18         open FILE, "$file" or die "can't open file";
19         while (<FILE>) {
20                 chomp;
21                 /^CONFIG_(.+?)=(.+)/ and do {
22                         $config{$1} = $2;
23                         next;
24                 };
25                 /^# CONFIG_(.+?) is not set/ and do {
26                         $config{$1} = "#undef";
27                         next;
28                 };
29                 /^#/ and next;
30                 /^(.+)$/ and print "WARNING: can't parse line: $1\n";
31         }
32         return \%config;
33 }
34
35
36 sub config_and($$) {
37         my $cfg1 = shift;
38         my $cfg2 = shift;
39         my %config;
40
41         foreach my $config (keys %$cfg1) {
42                 my $val1 = $cfg1->{$config};
43                 my $val2 = $cfg2->{$config};
44                 $val2 and ($val1 eq $val2) and do {
45                         $config{$config} = $val1;
46                 };
47         }
48         return \%config;
49 }
50
51
52 sub config_add($$$) {
53         my $cfg1 = shift;
54         my $cfg2 = shift;
55         my $mod_plus = shift;
56         my %config;
57         
58         for ($cfg1, $cfg2) {
59                 my %cfg = %$_;
60                 
61                 foreach my $config (keys %cfg) {
62                         next if $mod_plus and $config{$config} and $config{$config} eq "y";
63                         $config{$config} = $cfg{$config};
64                 }
65         }
66         return \%config;
67 }
68
69 sub config_diff($$) {
70         my $cfg1 = shift;
71         my $cfg2 = shift;
72         my %config;
73         
74         foreach my $config (keys %$cfg2) {
75                 if (!$cfg1->{$config} or $cfg1->{$config} ne $cfg2->{$config}) {
76                         $config{$config} = $cfg2->{$config};
77                 }
78         }
79         return \%config
80 }
81
82 sub config_sub($$) {
83         my $cfg1 = shift;
84         my $cfg2 = shift;
85         my %config = %{$cfg1};
86         
87         foreach my $config (keys %$cfg2) {
88                 delete $config{$config};
89         }
90         return \%config;
91 }
92
93 sub print_cfgline($$) {
94         my $name = shift;
95         my $val = shift;
96         if ($val eq '#undef') {
97                 print "# CONFIG_$name is not set\n";
98         } else {
99                 print "CONFIG_$name=$val\n";
100         }
101 }
102
103
104 sub dump_config($) {
105         my $cfg = shift;
106         die "argument error in dump_config" unless ($cfg);
107         my %config = %$cfg;
108         foreach my $config (sort keys %config) {
109                 print_cfgline($config, $config{$config});
110         }
111 }
112
113 sub parse_expr($);
114
115 sub parse_expr($) {
116         my $pos = shift;
117         my $arg = $arg[$$pos++];
118         
119         die "Parse error" if (!$arg);
120         
121         if ($arg eq '&') {
122                 my $arg1 = parse_expr($pos);
123                 my $arg2 = parse_expr($pos);
124                 return config_and($arg1, $arg2);
125         } elsif ($arg =~ /^\+/) {
126                 my $arg1 = parse_expr($pos);
127                 my $arg2 = parse_expr($pos);
128                 return config_add($arg1, $arg2, 0);
129         } elsif ($arg =~ /^m\+/) {
130                 my $arg1 = parse_expr($pos);
131                 my $arg2 = parse_expr($pos);
132                 return config_add($arg1, $arg2, 1);
133         } elsif ($arg eq '>') {
134                 my $arg1 = parse_expr($pos);
135                 my $arg2 = parse_expr($pos);
136                 return config_diff($arg1, $arg2);
137         } elsif ($arg eq '-') {
138                 my $arg1 = parse_expr($pos);
139                 my $arg2 = parse_expr($pos);
140                 return config_sub($arg1, $arg2);
141         } else {
142                 return load_config($arg);
143         }
144 }
145
146 my $pos = 0;
147 dump_config(parse_expr(\$pos));
148 die "Parse error" if ($arg[$pos]);