Subversion Repositories HelenOS-historic

Rev

Rev 568 | Rev 604 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 568 Rev 573
1
#!/usr/bin/env python
1
#!/usr/bin/env python
2
"""
2
"""
3
Kernel configuration script
3
Kernel configuration script
4
"""
4
"""
5
import sys
5
import sys
6
import os
6
import os
7
import re
7
import re
8
import commands
8
import commands
9
 
9
 
10
INPUT = 'kernel.config'
10
INPUT = 'kernel.config'
11
OUTPUT = 'Makefile.config'
11
OUTPUT = 'Makefile.config'
12
TMPOUTPUT = 'Makefile.config.tmp'
12
TMPOUTPUT = 'Makefile.config.tmp'
13
 
13
 
14
class DefaultDialog:
14
class DefaultDialog:
15
    "Wrapper dialog that tries to return default values"
15
    "Wrapper dialog that tries to return default values"
16
    def __init__(self, dlg):
16
    def __init__(self, dlg):
17
        self.dlg = dlg
17
        self.dlg = dlg
18
 
18
 
19
    def set_title(self,text):
19
    def set_title(self,text):
20
        self.dlg.set_title(text)
20
        self.dlg.set_title(text)
21
       
21
       
22
    def yesno(self, text, default=None):
22
    def yesno(self, text, default=None):
23
        if default is not None:
23
        if default is not None:
24
            return default
24
            return default
25
        return self.dlg.yesno(text, default)
25
        return self.dlg.yesno(text, default)
26
    def noyes(self, text, default=None):
26
    def noyes(self, text, default=None):
27
        if default is not None:
27
        if default is not None:
28
            return default
28
            return default
29
        return self.dlg.noyes(text, default)
29
        return self.dlg.noyes(text, default)
30
   
30
   
31
    def choice(self, text, choices, defopt=None):
31
    def choice(self, text, choices, defopt=None):
32
        if defopt is not None:
32
        if defopt is not None:
33
            return choices[defopt][0]
33
            return choices[defopt][0]
34
        return self.dlg.choice(text, choices, defopt)
34
        return self.dlg.choice(text, choices, defopt)
35
 
35
 
36
class NoDialog:
36
class NoDialog:
37
    def __init__(self):
37
    def __init__(self):
38
        self.printed = None
38
        self.printed = None
39
        self.title = 'HelenOS Configuration'
39
        self.title = 'HelenOS Configuration'
40
 
40
 
41
    def print_title(self):
41
    def print_title(self):
42
        if not self.printed:
42
        if not self.printed:
43
            sys.stdout.write("\n*** %s ***\n" % self.title)
43
            sys.stdout.write("\n*** %s ***\n" % self.title)
44
            self.printed = True
44
            self.printed = True
45
 
45
 
46
    def set_title(self, text):
46
    def set_title(self, text):
47
        self.title = text
47
        self.title = text
48
        self.printed = False
48
        self.printed = False
49
   
49
   
50
    def noyes(self, text, default=None):
50
    def noyes(self, text, default=None):
51
        if not default:
51
        if not default:
52
            default = 'n'
52
            default = 'n'
53
        return self.yesno(text, default)
53
        return self.yesno(text, default)
54
   
54
   
55
    def yesno(self, text, default=None):
55
    def yesno(self, text, default=None):
56
        self.print_title()
56
        self.print_title()
57
       
57
       
58
        if default != 'n':
58
        if default != 'n':
59
            default = 'y'
59
            default = 'y'
60
        while 1:
60
        while 1:
61
            sys.stdout.write("%s (y/n)[%s]: " % (text,default))
61
            sys.stdout.write("%s (y/n)[%s]: " % (text,default))
62
            inp = sys.stdin.readline()
62
            inp = sys.stdin.readline()
63
            if not inp:
63
            if not inp:
64
                raise EOFError
64
                raise EOFError
65
            inp = inp.strip().lower()
65
            inp = inp.strip().lower()
66
            if not inp:
66
            if not inp:
67
                return default
67
                return default
68
            if inp == 'y':
68
            if inp == 'y':
69
                return 'y'
69
                return 'y'
70
            elif inp == 'n':
70
            elif inp == 'n':
71
                return 'n'
71
                return 'n'
72
 
72
 
73
    def _print_choice(self, text, choices, defopt):
73
    def _print_choice(self, text, choices, defopt):
74
        sys.stdout.write('%s:\n' % text)
74
        sys.stdout.write('%s:\n' % text)
75
        for i,(text,descr) in enumerate(choices):
75
        for i,(text,descr) in enumerate(choices):
76
            sys.stdout.write('\t%2d. %s\n' % (i, descr))
76
            sys.stdout.write('\t%2d. %s\n' % (i, descr))
77
        if defopt is not None:
77
        if defopt is not None:
78
            sys.stdout.write('Enter choice number[%d]: ' % defopt)
78
            sys.stdout.write('Enter choice number[%d]: ' % defopt)
79
        else:
79
        else:
80
            sys.stdout.write('Enter choice number: ')
80
            sys.stdout.write('Enter choice number: ')
81
 
81
 
82
    def menu(self, text, choices, button, defopt=None):
82
    def menu(self, text, choices, button, defopt=None):
83
        menu = []
83
        menu = []
84
        for key, descr in choices:
84
        for key, descr in choices:
85
            txt = key + (45-len(key))*' ' + ': ' + descr
85
            txt = key + (45-len(key))*' ' + ': ' + descr
86
            menu.append((key, txt))
86
            menu.append((key, txt))
87
           
87
           
88
        return self.choice(text, [button] + menu)
88
        return self.choice(text, [button] + menu)
89
       
89
       
90
    def choice(self, text, choices, defopt=None):
90
    def choice(self, text, choices, defopt=None):
91
        self.print_title()
91
        self.print_title()
92
        while 1:
92
        while 1:
93
            self._print_choice(text, choices, defopt)
93
            self._print_choice(text, choices, defopt)
94
            inp = sys.stdin.readline()
94
            inp = sys.stdin.readline()
95
            if not inp:
95
            if not inp:
96
                raise EOFError
96
                raise EOFError
97
            if not inp.strip():
97
            if not inp.strip():
98
                if defopt is not None:
98
                if defopt is not None:
99
                    return choices[defopt][0]
99
                    return choices[defopt][0]
100
                continue
100
                continue
101
            try:
101
            try:
102
                number = int(inp.strip())
102
                number = int(inp.strip())
103
            except ValueError:
103
            except ValueError:
104
                continue
104
                continue
105
            if number < 0 or number >= len(choices):
105
            if number < 0 or number >= len(choices):
106
                continue
106
                continue
107
            return choices[number][0]
107
            return choices[number][0]
108
 
108
 
109
 
109
 
110
class Dialog(NoDialog):
110
class Dialog(NoDialog):
111
    def __init__(self):
111
    def __init__(self):
112
        NoDialog.__init__(self)
112
        NoDialog.__init__(self)
113
        self.dlgcmd = os.environ.get('DIALOG','dialog')
113
        self.dlgcmd = os.environ.get('DIALOG','dialog')
114
        self.title = ''
114
        self.title = ''
115
        self.backtitle = 'HelenOS Kernel Configuration'
115
        self.backtitle = 'HelenOS Kernel Configuration'
116
       
116
       
117
        if os.system('%s --print-maxsize >/dev/null 2>&1' % self.dlgcmd) != 0:
117
        if os.system('%s --print-maxsize >/dev/null 2>&1' % self.dlgcmd) != 0:
118
            raise NotImplementedError
118
            raise NotImplementedError
119
 
119
 
120
    def set_title(self,text):
120
    def set_title(self,text):
121
        self.title = text
121
        self.title = text
122
       
122
       
123
    def calldlg(self,*args,**kw):
123
    def calldlg(self,*args,**kw):
124
        "Wrapper for calling 'dialog' program"
124
        "Wrapper for calling 'dialog' program"
125
        indesc, outdesc = os.pipe()
125
        indesc, outdesc = os.pipe()
126
        pid = os.fork()
126
        pid = os.fork()
127
        if not pid:
127
        if not pid:
128
            os.close(2)
128
            os.close(2)
129
            os.dup(outdesc)
129
            os.dup(outdesc)
130
            os.close(indesc)
130
            os.close(indesc)
131
           
131
           
132
            dlgargs = [self.dlgcmd,'--title',self.title,
132
            dlgargs = [self.dlgcmd,'--title',self.title,
133
                       '--backtitle', self.backtitle]
133
                       '--backtitle', self.backtitle]
134
            for key,val in kw.items():
134
            for key,val in kw.items():
135
                dlgargs.append('--'+key)
135
                dlgargs.append('--'+key)
136
                dlgargs.append(val)
136
                dlgargs.append(val)
137
            dlgargs += args            
137
            dlgargs += args            
138
            os.execlp(self.dlgcmd,*dlgargs)
138
            os.execlp(self.dlgcmd,*dlgargs)
139
 
139
 
140
        os.close(outdesc)
140
        os.close(outdesc)
141
       
141
       
142
        try:
142
        try:
143
            errout = os.fdopen(indesc,'r')
143
            errout = os.fdopen(indesc,'r')
144
            data = errout.read()
144
            data = errout.read()
145
            errout.close()
145
            errout.close()
146
            pid,status = os.wait()
146
            pid,status = os.wait()
147
        except:
147
        except:
148
            os.system('reset') # Reset terminal
148
            os.system('reset') # Reset terminal
149
            raise
149
            raise
150
       
150
       
151
        if not os.WIFEXITED(status):
151
        if not os.WIFEXITED(status):
152
            os.system('reset') # Reset terminal
152
            os.system('reset') # Reset terminal
153
            raise EOFError
153
            raise EOFError
154
       
154
       
155
        status = os.WEXITSTATUS(status)
155
        status = os.WEXITSTATUS(status)
156
        if status == 255:
156
        if status == 255:
157
            raise EOFError
157
            raise EOFError
158
        return status,data
158
        return status,data
159
       
159
       
160
    def yesno(self, text, default=None):
160
    def yesno(self, text, default=None):
161
        if text[-1] not in ('?',':'):
161
        if text[-1] not in ('?',':'):
162
            text = text + ':'
162
            text = text + ':'
163
        width = '50'
163
        width = '50'
164
        height = '5'
164
        height = '5'
165
        if len(text) < 48:
165
        if len(text) < 48:
166
            text = ' '*int(((48-len(text))/2)) + text
166
            text = ' '*int(((48-len(text))/2)) + text
167
        else:
167
        else:
168
            width = '0'
168
            width = '0'
169
            height = '0'
169
            height = '0'
170
        if default == 'n':
170
        if default == 'n':
171
            res,data = self.calldlg('--defaultno','--yesno',text,height,width)
171
            res,data = self.calldlg('--defaultno','--yesno',text,height,width)
172
        else:
172
        else:
173
            res,data = self.calldlg('--yesno',text,height,width)
173
            res,data = self.calldlg('--yesno',text,height,width)
174
 
174
 
175
        if res == 0:
175
        if res == 0:
176
            return 'y'
176
            return 'y'
177
        return 'n'
177
        return 'n'
178
 
178
 
179
    def menu(self, text, choices, button, defopt=None):
179
    def menu(self, text, choices, button, defopt=None):
180
        text = text + ':'
180
        text = text + ':'
181
        width = '70'
181
        width = '70'
182
        height = str(8 + len(choices))
182
        height = str(8 + len(choices))
183
        args = []
183
        args = []
184
        for key,val in choices:
184
        for key,val in choices:
185
            args.append(key)
185
            args.append(key)
186
            args.append(val)
186
            args.append(val)
187
 
187
 
188
        kw = {}
188
        kw = {}
189
        if defopt:
189
        if defopt:
190
            kw['default-item'] = choices[defopt][0]
190
            kw['default-item'] = choices[defopt][0]
191
        res,data = self.calldlg('--ok-label','Change',
191
        res,data = self.calldlg('--ok-label','Change',
192
                                '--extra-label',button[1],
192
                                '--extra-label',button[1],
193
                                '--extra-button',
193
                                '--extra-button',
194
                                '--menu',text,height,width,
194
                                '--menu',text,height,width,
195
                                str(len(choices)),*args,**kw)
195
                                str(len(choices)),*args,**kw)
196
        if res == 3:
196
        if res == 3:
197
            return button[0]
197
            return button[0]
198
        if res == 1: # Cancel
198
        if res == 1: # Cancel
199
            sys.exit(1)
199
            sys.exit(1)
200
        elif res:
200
        elif res:
201
            print data
201
            print data
202
            raise EOFError
202
            raise EOFError
203
        return data
203
        return data
204
   
204
   
205
    def choice(self, text, choices, defopt=None):
205
    def choice(self, text, choices, defopt=None):
206
        text = text + ':'
206
        text = text + ':'
207
        width = '50'
207
        width = '50'
208
        height = str(8 + len(choices))
208
        height = str(8 + len(choices))
209
        args = []
209
        args = []
210
        for key,val in choices:
210
        for key,val in choices:
211
            args.append(key)
211
            args.append(key)
212
            args.append(val)
212
            args.append(val)
213
 
213
 
214
        kw = {}
214
        kw = {}
215
        if defopt:
215
        if defopt:
216
            kw['default-item'] = choices[defopt][0]
216
            kw['default-item'] = choices[defopt][0]
217
        res,data = self.calldlg('--nocancel','--menu',text,height,width,
217
        res,data = self.calldlg('--nocancel','--menu',text,height,width,
218
                                str(len(choices)),*args, **kw)
218
                                str(len(choices)),*args, **kw)
219
        if res:
219
        if res:
220
            print data
220
            print data
221
            raise EOFError
221
            raise EOFError
222
        return data
222
        return data
223
   
223
   
224
def read_defaults(fname,defaults):
224
def read_defaults(fname,defaults):
225
    "Read saved values from last configuration run"
225
    "Read saved values from last configuration run"
226
    f = file(fname,'r')
226
    f = file(fname,'r')
227
    for line in f:
227
    for line in f:
228
        res = re.match(r'^(?:#!# )?([^#]\w*)\s*=\s*(.*?)\s*$', line)
228
        res = re.match(r'^(?:#!# )?([^#]\w*)\s*=\s*(.*?)\s*$', line)
229
        if res:
229
        if res:
230
            defaults[res.group(1)] = res.group(2)
230
            defaults[res.group(1)] = res.group(2)
231
    f.close()
231
    f.close()
232
 
232
 
233
def check_condition(text, defaults, asked_names):
233
def check_condition(text, defaults, asked_names):
234
    seen_vars = [ x[0] for x in asked_names ]
234
    seen_vars = [ x[0] for x in asked_names ]
235
    ctype = 'cnf'
235
    ctype = 'cnf'
236
    if ')|' in text or '|(' in text:
236
    if ')|' in text or '|(' in text:
237
        ctype = 'dnf'
237
        ctype = 'dnf'
238
   
238
   
239
    if ctype == 'cnf':
239
    if ctype == 'cnf':
240
        conds = text.split('&')
240
        conds = text.split('&')
241
    else:
241
    else:
242
        conds = text.split('|')
242
        conds = text.split('|')
243
 
243
 
244
    for cond in conds:
244
    for cond in conds:
245
        if cond.startswith('(') and cond.endswith(')'):
245
        if cond.startswith('(') and cond.endswith(')'):
246
            cond = cond[1:-1]
246
            cond = cond[1:-1]
247
           
247
           
248
        inside = check_inside(cond, defaults, ctype, seen_vars)
248
        inside = check_inside(cond, defaults, ctype, seen_vars)
249
       
249
       
250
        if ctype == 'cnf' and not inside:
250
        if ctype == 'cnf' and not inside:
251
            return False
251
            return False
252
        if ctype == 'dnf' and inside:
252
        if ctype == 'dnf' and inside:
253
            return True
253
            return True
254
 
254
 
255
    if ctype == 'cnf':
255
    if ctype == 'cnf':
256
        return True
256
        return True
257
    return False
257
    return False
258
 
258
 
259
def check_inside(text, defaults, ctype, seen_vars):
259
def check_inside(text, defaults, ctype, seen_vars):
260
    """
260
    """
261
    Check that the condition specified on input line is True
261
    Check that the condition specified on input line is True
262
 
262
 
263
    only CNF is supported
263
    only CNF is supported
264
    """
264
    """
265
    if ctype == 'cnf':
265
    if ctype == 'cnf':
266
        conds = text.split('|')
266
        conds = text.split('|')
267
    else:
267
    else:
268
        conds = text.split('&')
268
        conds = text.split('&')
269
    for cond in conds:
269
    for cond in conds:
270
        res = re.match(r'^(.*?)(!?=)(.*)$', cond)
270
        res = re.match(r'^(.*?)(!?=)(.*)$', cond)
271
        if not res:
271
        if not res:
272
            raise RuntimeError("Invalid condition: %s" % cond)
272
            raise RuntimeError("Invalid condition: %s" % cond)
273
        condname = res.group(1)
273
        condname = res.group(1)
274
        oper = res.group(2)
274
        oper = res.group(2)
275
        condval = res.group(3)
275
        condval = res.group(3)
276
        if condname not in seen_vars:
276
        if condname not in seen_vars:
277
            raise RuntimeError("Variable %s not defined before being asked." %\
277
            raise RuntimeError("Variable %s not defined before being asked." %\
278
                               condname)
278
                               condname)
279
        if not defaults.has_key(condname):
279
        if not defaults.has_key(condname):
280
            raise RuntimeError("Condition var %s does not exist: %s" % \
280
            raise RuntimeError("Condition var %s does not exist: %s" % \
281
                               (condname,text))
281
                               (condname,text))
282
 
282
 
283
        if ctype == 'cnf':
283
        if ctype == 'cnf':
284
            if oper == '=' and  condval == defaults[condname]:
284
            if oper == '=' and  condval == defaults[condname]:
285
                return True
285
                return True
286
            if oper == '!=' and condval != defaults[condname]:
286
            if oper == '!=' and condval != defaults[condname]:
287
                return True
287
                return True
288
        else:
288
        else:
289
            if oper== '=' and condval != defaults[condname]:
289
            if oper== '=' and condval != defaults[condname]:
290
                return False
290
                return False
291
            if oper== '!=' and condval == defaults[condname]:
291
            if oper== '!=' and condval == defaults[condname]:
292
                print 2
-
 
293
                return False
292
                return False
294
    if ctype=='cnf':
293
    if ctype=='cnf':
295
        return False
294
        return False
296
    return True
295
    return True
297
 
296
 
298
def parse_config(input, output, dlg, defaults={}, askonly=None):
297
def parse_config(input, output, dlg, defaults={}, askonly=None):
299
    "Parse configuration file and create Makefile.config on the fly"
298
    "Parse configuration file and create Makefile.config on the fly"
300
    def ask_the_question(dialog):
299
    def ask_the_question(dialog):
301
        "Ask question based on the type of variables to ask"
300
        "Ask question based on the type of variables to ask"
302
        # This is quite a hack, this thingy is written just to
301
        # This is quite a hack, this thingy is written just to
303
        # have access to local variables..
302
        # have access to local variables..
304
        if vartype == 'y/n':
303
        if vartype == 'y/n':
305
            return dialog.yesno(comment, default)
304
            return dialog.yesno(comment, default)
306
        elif vartype == 'n/y':
305
        elif vartype == 'n/y':
307
            return dialog.noyes(comment, default)
306
            return dialog.noyes(comment, default)
308
        elif vartype == 'choice':
307
        elif vartype == 'choice':
309
            defopt = None
308
            defopt = None
310
            if default is not None:
309
            if default is not None:
311
                for i,(key,val) in enumerate(choices):
310
                for i,(key,val) in enumerate(choices):
312
                    if key == default:
311
                    if key == default:
313
                        defopt = i
312
                        defopt = i
314
                        break
313
                        break
315
            return dialog.choice(comment, choices, defopt)
314
            return dialog.choice(comment, choices, defopt)
316
        else:
315
        else:
317
            raise RuntimeError("Bad method: %s" % vartype)
316
            raise RuntimeError("Bad method: %s" % vartype)
318
 
317
 
319
   
318
   
320
    f = file(input, 'r')
319
    f = file(input, 'r')
321
    outf = file(output, 'w')
320
    outf = file(output, 'w')
322
 
321
 
323
    outf.write('#########################################\n')
322
    outf.write('#########################################\n')
324
    outf.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n')
323
    outf.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n')
325
    outf.write('#########################################\n\n')
324
    outf.write('#########################################\n\n')
326
 
325
 
327
    asked_names = []
326
    asked_names = []
328
 
327
 
329
    comment = ''
328
    comment = ''
330
    default = None
329
    default = None
331
    choices = []
330
    choices = []
332
    for line in f:
331
    for line in f:
333
        if line.startswith('%'):
332
        if line.startswith('%'):
334
            res = re.match(r'^%\s*(?:\[(.*?)\])?\s*(.*)$', line)
333
            res = re.match(r'^%\s*(?:\[(.*?)\])?\s*(.*)$', line)
335
            if not res:
334
            if not res:
336
                raise RuntimeError('Invalid command: %s' % line)
335
                raise RuntimeError('Invalid command: %s' % line)
337
            if res.group(1):
336
            if res.group(1):
338
                if not check_condition(res.group(1), defaults,
337
                if not check_condition(res.group(1), defaults,
339
                                       asked_names):
338
                                       asked_names):
340
                    continue
339
                    continue
341
            args = res.group(2).strip().split(' ')
340
            args = res.group(2).strip().split(' ')
342
            cmd = args[0].lower()
341
            cmd = args[0].lower()
343
            args = args[1:]
342
            args = args[1:]
344
            if cmd == 'saveas':
343
            if cmd == 'saveas':
345
                outf.write('%s = %s\n' % (args[1],defaults[args[0]]))
344
                outf.write('%s = %s\n' % (args[1],defaults[args[0]]))
346
            elif cmd == 'shellcmd':
345
            elif cmd == 'shellcmd':
347
                varname = args[0]
346
                varname = args[0]
348
                args = args[1:]
347
                args = args[1:]
349
                for i,arg in enumerate(args):
348
                for i,arg in enumerate(args):
350
                    if arg.startswith('$'):
349
                    if arg.startswith('$'):
351
                        args[i] = defaults[arg[1:]]
350
                        args[i] = defaults[arg[1:]]
352
                data,status = commands.getstatusoutput(' '.join(args))
351
                data,status = commands.getstatusoutput(' '.join(args))
353
                if status:
352
                if status:
354
                    raise RuntimeError('Error running: %s' % ' '.join(args))
353
                    raise RuntimeError('Error running: %s' % ' '.join(args))
355
                outf.write('%s = %s\n' % (varname,data.strip()))
354
                outf.write('%s = %s\n' % (varname,data.strip()))
356
            continue
355
            continue
357
           
356
           
358
        if line.startswith('!'):
357
        if line.startswith('!'):
359
            # Ask a question
358
            # Ask a question
360
            res = re.search(r'!\s*(?:\[(.*?)\])?\s*([^\s]+)\s*\((.*)\)\s*$', line)
359
            res = re.search(r'!\s*(?:\[(.*?)\])?\s*([^\s]+)\s*\((.*)\)\s*$', line)
361
            if not res:
360
            if not res:
362
                raise RuntimeError("Weird line: %s" % line)
361
                raise RuntimeError("Weird line: %s" % line)
363
            varname = res.group(2)
362
            varname = res.group(2)
364
            vartype = res.group(3)
363
            vartype = res.group(3)
365
 
364
 
366
            default = defaults.get(varname,None)
365
            default = defaults.get(varname,None)
367
           
366
           
368
            if res.group(1):
367
            if res.group(1):
369
                if not check_condition(res.group(1), defaults,
368
                if not check_condition(res.group(1), defaults,
370
                                       asked_names):
369
                                       asked_names):
371
                    if default is not None:
370
                    if default is not None:
372
                        outf.write('#!# %s = %s\n' % (varname, default))
371
                        outf.write('#!# %s = %s\n' % (varname, default))
373
                    # Clear cumulated values
372
                    # Clear cumulated values
374
                    comment = ''
373
                    comment = ''
375
                    default = None
374
                    default = None
376
                    choices = []
375
                    choices = []
377
                    continue
376
                    continue
378
               
377
               
379
            asked_names.append((varname,comment))
378
            asked_names.append((varname,comment))
380
 
379
 
381
            if default is None or not askonly or askonly == varname:
380
            if default is None or not askonly or askonly == varname:
382
                default = ask_the_question(dlg)
381
                default = ask_the_question(dlg)
383
            else:
382
            else:
384
                default = ask_the_question(DefaultDialog(dlg))
383
                default = ask_the_question(DefaultDialog(dlg))
385
 
384
 
386
            outf.write('%s = %s\n' % (varname, default))
385
            outf.write('%s = %s\n' % (varname, default))
387
            # Remeber the selected value
386
            # Remeber the selected value
388
            defaults[varname] = default
387
            defaults[varname] = default
389
            # Clear cumulated values
388
            # Clear cumulated values
390
            comment = ''
389
            comment = ''
391
            default = None
390
            default = None
392
            choices = []
391
            choices = []
393
            continue
392
            continue
394
       
393
       
395
        if line.startswith('@'):
394
        if line.startswith('@'):
396
            # Add new line into the 'choice array' 
395
            # Add new line into the 'choice array' 
397
            res = re.match(r'@\s*(?:\[(.*?)\])?\s*"(.*?)"\s*(.*)$', line)
396
            res = re.match(r'@\s*(?:\[(.*?)\])?\s*"(.*?)"\s*(.*)$', line)
398
            if not res:
397
            if not res:
399
                raise RuntimeError("Bad line: %s" % line)
398
                raise RuntimeError("Bad line: %s" % line)
400
            if res.group(1):
399
            if res.group(1):
401
                if not check_condition(res.group(1),defaults,
400
                if not check_condition(res.group(1),defaults,
402
                                       asked_names):
401
                                       asked_names):
403
                    continue
402
                    continue
404
            choices.append((res.group(2), res.group(3)))
403
            choices.append((res.group(2), res.group(3)))
405
            continue
404
            continue
406
 
405
 
407
        # All other things print to output file
406
        # All other things print to output file
408
        outf.write(line)
407
        outf.write(line)
409
        if re.match(r'^#[^#]', line):
408
        if re.match(r'^#[^#]', line):
410
            # Last comment before question will be displayed to the user
409
            # Last comment before question will be displayed to the user
411
            comment = line[1:].strip()
410
            comment = line[1:].strip()
412
        elif line.startswith('## '):
411
        elif line.startswith('## '):
413
            # Set title of the dialog window
412
            # Set title of the dialog window
414
            dlg.set_title(line[2:].strip())
413
            dlg.set_title(line[2:].strip())
415
 
414
 
416
    outf.write('\n')
415
    outf.write('\n')
417
    outf.write('REVISION=%s\n' % commands.getoutput('svnversion . 2> /dev/null'))
416
    outf.write('REVISION=%s\n' % commands.getoutput('svnversion . 2> /dev/null'))
418
    outf.write('TIMESTAMP=%s\n' % commands.getoutput('date "+%Y-%m-%d %H:%M:%S"'))
417
    outf.write('TIMESTAMP=%s\n' % commands.getoutput('date "+%Y-%m-%d %H:%M:%S"'))
419
    outf.close()
418
    outf.close()
420
    f.close()
419
    f.close()
421
    return asked_names
420
    return asked_names
422
 
421
 
423
def main():
422
def main():
424
    defaults = {}
423
    defaults = {}
425
    try:
424
    try:
426
        dlg = Dialog()
425
        dlg = Dialog()
427
    except NotImplementedError:
426
    except NotImplementedError:
428
        dlg = NoDialog()
427
        dlg = NoDialog()
429
 
428
 
430
    if len(sys.argv) == 2 and sys.argv[1]=='default':
429
    if len(sys.argv) == 2 and sys.argv[1]=='default':
431
        defmode = True
430
        defmode = True
432
    else:
431
    else:
433
        defmode = False
432
        defmode = False
434
 
433
 
435
    # Default run will update the configuration file
434
    # Default run will update the configuration file
436
    # with newest options
435
    # with newest options
437
    if os.path.exists(OUTPUT):
436
    if os.path.exists(OUTPUT):
438
        read_defaults(OUTPUT, defaults)
437
        read_defaults(OUTPUT, defaults)
439
 
438
 
440
    # Dry run only with defaults
439
    # Dry run only with defaults
441
    varnames = parse_config(INPUT, TMPOUTPUT, DefaultDialog(dlg), defaults)
440
    varnames = parse_config(INPUT, TMPOUTPUT, DefaultDialog(dlg), defaults)
442
    # If not in default mode, present selection of all possibilities
441
    # If not in default mode, present selection of all possibilities
443
    if not defmode:
442
    if not defmode:
444
        defopt = 0
443
        defopt = 0
445
        while 1:
444
        while 1:
446
            # varnames contains variable names that were in the
445
            # varnames contains variable names that were in the
447
            # last question set
446
            # last question set
448
            choices = [ (x[1],defaults[x[0]]) for x in varnames ]
447
            choices = [ (x[1],defaults[x[0]]) for x in varnames ]
449
            res = dlg.menu('Configuration',choices,('save','Save'),defopt)
448
            res = dlg.menu('Configuration',choices,('save','Save'),defopt)
450
            if res == 'save':
449
            if res == 'save':
451
                parse_config(INPUT, TMPOUTPUT, DefaultDialog(dlg), defaults)
450
                parse_config(INPUT, TMPOUTPUT, DefaultDialog(dlg), defaults)
452
                break
451
                break
453
            # transfer description back to varname
452
            # transfer description back to varname
454
            for i,(vname,descr) in enumerate(varnames):
453
            for i,(vname,descr) in enumerate(varnames):
455
                if res == descr:
454
                if res == descr:
456
                    defopt = i
455
                    defopt = i
457
                    break
456
                    break
458
            # Ask the user a simple question, produce output
457
            # Ask the user a simple question, produce output
459
            # as if the user answered all the other questions
458
            # as if the user answered all the other questions
460
            # with default answer
459
            # with default answer
461
            varnames = parse_config(INPUT, TMPOUTPUT, dlg, defaults,
460
            varnames = parse_config(INPUT, TMPOUTPUT, dlg, defaults,
462
                                    askonly=varnames[i][0])
461
                                    askonly=varnames[i][0])
463
       
462
       
464
   
463
   
465
    if os.path.exists(OUTPUT):
464
    if os.path.exists(OUTPUT):
466
        os.unlink(OUTPUT)
465
        os.unlink(OUTPUT)
467
    os.rename(TMPOUTPUT, OUTPUT)
466
    os.rename(TMPOUTPUT, OUTPUT)
468
   
467
   
469
    if not defmode and dlg.yesno('Rebuild kernel?') == 'y':
468
    if not defmode and dlg.yesno('Rebuild kernel?') == 'y':
470
        os.execlp('make','make','clean','build')
469
        os.execlp('make','make','clean','build')
471
 
470
 
472
if __name__ == '__main__':
471
if __name__ == '__main__':
473
    main()
472
    main()
474
 
473