major target cleanup. it is now possible to have subtargets that can override many...
[openwrt/svn-archive/archive.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]);