Subversion Repositories HelenOS-historic

Rev

Rev 1651 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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