1# This script runs `make config' to generate a Linux kernel
2# configuration file. For each question (i.e. kernel configuration
3# option), unless an override is provided, it answers "m" if possible,
4# and otherwise uses the default answer (as determined by the default
5# config for the architecture). Overrides are read from the file
6# $KERNEL_CONFIG, which on each line contains an option name and an
7# answer, e.g. "EXT2_FS_POSIX_ACL y". The script warns about ignored
8# options in $KERNEL_CONFIG, and barfs if `make config' selects
9# another answer for an option than the one provided in
10# $KERNEL_CONFIG.
11
12use strict;
13use IPC::Open2;
14use Cwd;
15
16my $wd = getcwd;
17
18my $debug = $ENV{'DEBUG'};
19my $autoModules = $ENV{'AUTO_MODULES'};
20
21$SIG{PIPE} = 'IGNORE';
22
23# Read the answers.
24my %answers;
25my %requiredAnswers;
26open ANSWERS, "<$ENV{KERNEL_CONFIG}" or die;
27while (<ANSWERS>) {
28 chomp;
29 s/#.*//;
30 if (/^\s*([A-Za-z0-9_]+)(\?)?\s+(\S+)\s*$/) {
31 $answers{$1} = $3;
32 $requiredAnswers{$1} = !(defined $2);
33 } elsif (!/^\s*$/) {
34 die "invalid config line: $_";
35 }
36}
37close ANSWERS;
38
39sub runConfig {
40
41 # Run `make config'.
42 my $pid = open2(\*IN, \*OUT, "make -C $ENV{SRC} O=$wd config SHELL=bash ARCH=$ENV{ARCH}");
43
44 # Parse the output, look for questions and then send an
45 # appropriate answer.
46 my $line = ""; my $s;
47 my %choices = ();
48
49 my ($prevQuestion, $prevName);
50
51 while (!eof IN) {
52 read IN, $s, 1 or next;
53 $line .= $s;
54
55 #print STDERR "LINE: $line\n";
56
57 if ($s eq "\n") {
58 print STDERR "GOT: $line" if $debug;
59
60 # Remember choice alternatives ("> 1. bla (FOO)" or " 2. bla (BAR) (NEW)").
61 if ($line =~ /^\s*>?\s*(\d+)\.\s+.*?\(([A-Za-z0-9_]+)\)(?:\s+\(NEW\))?\s*$/) {
62 $choices{$2} = $1;
63 }
64
65 $line = "";
66 }
67
68 elsif ($line =~ /###$/) {
69 # The config program is waiting for an answer.
70
71 # Is this a regular question? ("bla bla (OPTION_NAME) [Y/n/m/...] ")
72 if ($line =~ /(.*) \(([A-Za-z0-9_]+)\) \[(.*)\].*###$/) {
73 my $question = $1; my $name = $2; my $alts = $3;
74 my $answer = "";
75 # Build everything as a module if possible.
76 $answer = "m" if $autoModules && $alts =~ /\/m/;
77 $answer = $answers{$name} if defined $answers{$name};
78 print STDERR "QUESTION: $question, NAME: $name, ALTS: $alts, ANSWER: $answer\n" if $debug;
79 print OUT "$answer\n";
80 die "repeated question: $question" if $prevQuestion && $prevQuestion eq $question && $name eq $prevName;
81 $prevQuestion = $question;
82 $prevName = $name;
83 }
84
85 # Is this a choice? ("choice[1-N]: ")
86 elsif ($line =~ /choice\[(.*)\]: ###$/) {
87 my $answer = "";
88 foreach my $name (keys %choices) {
89 $answer = $choices{$name} if ($answers{$name} || "") eq "y";
90 }
91 print STDERR "CHOICE: $1, ANSWER: $answer\n" if $debug;
92 print OUT "$answer\n" if $1 =~ /-/;
93 }
94
95 # Some questions lack the option name ("bla bla [Y/n/m/...] ").
96 elsif ($line =~ /(.*) \[(.*)\] ###$/) {
97 print OUT "\n";
98 }
99
100 else {
101 warn "don't know how to answer this question: $line\n";
102 print OUT "\n";
103 }
104
105 $line = "";
106 %choices = ();
107 }
108 }
109
110 close IN;
111 waitpid $pid, 0;
112}
113
114# Run `make config' several times to converge on the desired result.
115# (Some options may only become available after other options are
116# set in a previous run.)
117runConfig;
118runConfig;
119
120# Read the final .config file and check that our answers are in
121# there. `make config' often overrides answers if later questions
122# cause options to be selected.
123my %config;
124open CONFIG, "<.config" or die;
125while (<CONFIG>) {
126 chomp;
127 if (/^CONFIG_([A-Za-z0-9_]+)=(.*)$/) {
128 $config{$1} = $2;
129 } elsif (/^# CONFIG_([A-Za-z0-9_]+) is not set$/) {
130 $config{$1} = "n";
131 }
132}
133close CONFIG;
134
135foreach my $name (sort (keys %answers)) {
136 my $f = $requiredAnswers{$name} && $ENV{'ignoreConfigErrors'} ne "1"
137 ? sub { die "error: " . $_[0]; } : sub { warn "warning: " . $_[0]; };
138 &$f("unused option: $name\n") unless defined $config{$name};
139 &$f("option not set correctly: $name\n")
140 if $config{$name} && $config{$name} ne $answers{$name};
141}