Subversion Repositories HelenOS-historic

Rev

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

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