Subversion Repositories HelenOS-historic

Rev

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

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