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