Subversion Repositories HelenOS

Rev

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

Rev 4080 Rev 4081
1
#!/usr/bin/env python
1
#!/usr/bin/env python
2
#
2
#
3
# Copyright (c) 2006 Ondrej Palkovsky
3
# Copyright (c) 2006 Ondrej Palkovsky
4
# Copyright (c) 2009 Martin Decky
4
# Copyright (c) 2009 Martin Decky
5
# All rights reserved.
5
# All rights reserved.
6
#
6
#
7
# Redistribution and use in source and binary forms, with or without
7
# Redistribution and use in source and binary forms, with or without
8
# modification, are permitted provided that the following conditions
8
# modification, are permitted provided that the following conditions
9
# are met:
9
# are met:
10
#
10
#
11
# - Redistributions of source code must retain the above copyright
11
# - Redistributions of source code must retain the above copyright
12
#   notice, this list of conditions and the following disclaimer.
12
#   notice, this list of conditions and the following disclaimer.
13
# - Redistributions in binary form must reproduce the above copyright
13
# - Redistributions in binary form must reproduce the above copyright
14
#   notice, this list of conditions and the following disclaimer in the
14
#   notice, this list of conditions and the following disclaimer in the
15
#   documentation and/or other materials provided with the distribution.
15
#   documentation and/or other materials provided with the distribution.
16
# - The name of the author may not be used to endorse or promote products
16
# - The name of the author may not be used to endorse or promote products
17
#   derived from this software without specific prior written permission.
17
#   derived from this software without specific prior written permission.
18
#
18
#
19
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
#
29
#
30
"""
30
"""
31
HelenOS configuration system
31
HelenOS configuration system
32
"""
32
"""
33
import sys
33
import sys
34
import os
34
import os
35
import re
35
import re
36
import commands
36
import commands
37
import xtui
37
import xtui
38
 
38
 
39
INPUT = sys.argv[1]
39
INPUT = sys.argv[1]
40
MAKEFILE = 'Makefile.config'
40
MAKEFILE = 'Makefile.config'
41
MACROS = 'config.h'
41
MACROS = 'config.h'
42
DEFS = 'config.defs'
42
DEFS = 'config.defs'
43
PRECONF = 'defaults'
43
PRECONF = 'defaults'
44
 
44
 
45
def read_defaults(fname, defaults):
45
def read_defaults(fname, defaults):
46
    "Read saved values from last configuration run"
46
    "Read saved values from last configuration run"
47
   
47
   
48
    inf = file(fname, 'r')
48
    inf = file(fname, 'r')
49
   
49
   
50
    for line in inf:
50
    for line in inf:
51
        res = re.match(r'^(?:#!# )?([^#]\w*)\s*=\s*(.*?)\s*$', line)
51
        res = re.match(r'^(?:#!# )?([^#]\w*)\s*=\s*(.*?)\s*$', line)
52
        if (res):
52
        if (res):
53
            defaults[res.group(1)] = res.group(2)
53
            defaults[res.group(1)] = res.group(2)
54
   
54
   
55
    inf.close()
55
    inf.close()
56
 
56
 
57
def check_condition(text, defaults, ask_names):
57
def check_condition(text, defaults, ask_names):
58
    "Check that the condition specified on input line is True (only CNF and DNF is supported)"
58
    "Check that the condition specified on input line is True (only CNF and DNF is supported)"
59
   
59
   
60
    ctype = 'cnf'
60
    ctype = 'cnf'
61
   
61
   
62
    if ((')|' in text) or ('|(' in text)):
62
    if ((')|' in text) or ('|(' in text)):
63
        ctype = 'dnf'
63
        ctype = 'dnf'
64
   
64
   
65
    if (ctype == 'cnf'):
65
    if (ctype == 'cnf'):
66
        conds = text.split('&')
66
        conds = text.split('&')
67
    else:
67
    else:
68
        conds = text.split('|')
68
        conds = text.split('|')
69
   
69
   
70
    for cond in conds:
70
    for cond in conds:
71
        if (cond.startswith('(')) and (cond.endswith(')')):
71
        if (cond.startswith('(')) and (cond.endswith(')')):
72
            cond = cond[1:-1]
72
            cond = cond[1:-1]
73
       
73
       
74
        inside = check_inside(cond, defaults, ctype)
74
        inside = check_inside(cond, defaults, ctype)
75
       
75
       
76
        if (ctype == 'cnf') and (not inside):
76
        if (ctype == 'cnf') and (not inside):
77
            return False
77
            return False
78
       
78
       
79
        if (ctype == 'dnf') and (inside):
79
        if (ctype == 'dnf') and (inside):
80
            return True
80
            return True
81
   
81
   
82
    if (ctype == 'cnf'):
82
    if (ctype == 'cnf'):
83
        return True
83
        return True
84
    return False
84
    return False
85
 
85
 
86
def check_inside(text, defaults, ctype):
86
def check_inside(text, defaults, ctype):
87
    "Check for condition"
87
    "Check for condition"
88
   
88
   
89
    if (ctype == 'cnf'):
89
    if (ctype == 'cnf'):
90
        conds = text.split('|')
90
        conds = text.split('|')
91
    else:
91
    else:
92
        conds = text.split('&')
92
        conds = text.split('&')
93
   
93
   
94
    for cond in conds:
94
    for cond in conds:
95
        res = re.match(r'^(.*?)(!?=)(.*)$', cond)
95
        res = re.match(r'^(.*?)(!?=)(.*)$', cond)
96
        if (not res):
96
        if (not res):
97
            raise RuntimeError("Invalid condition: %s" % cond)
97
            raise RuntimeError("Invalid condition: %s" % cond)
98
       
98
       
99
        condname = res.group(1)
99
        condname = res.group(1)
100
        oper = res.group(2)
100
        oper = res.group(2)
101
        condval = res.group(3)
101
        condval = res.group(3)
102
       
102
       
103
        if (not defaults.has_key(condname)):
103
        if (not defaults.has_key(condname)):
104
            varval = ''
104
            varval = ''
105
        else:
105
        else:
106
            varval = defaults[condname]
106
            varval = defaults[condname]
107
            if (varval == '*'):
107
            if (varval == '*'):
108
                varval = 'y'
108
                varval = 'y'
109
       
109
       
110
        if (ctype == 'cnf'):
110
        if (ctype == 'cnf'):
111
            if (oper == '=') and (condval == varval):
111
            if (oper == '=') and (condval == varval):
112
                return True
112
                return True
113
       
113
       
114
            if (oper == '!=') and (condval != varval):
114
            if (oper == '!=') and (condval != varval):
115
                return True
115
                return True
116
        else:
116
        else:
117
            if (oper == '=') and (condval != varval):
117
            if (oper == '=') and (condval != varval):
118
                return False
118
                return False
119
           
119
           
120
            if (oper == '!=') and (condval == varval):
120
            if (oper == '!=') and (condval == varval):
121
                return False
121
                return False
122
   
122
   
123
    if (ctype == 'cnf'):
123
    if (ctype == 'cnf'):
124
        return False
124
        return False
125
   
125
   
126
    return True
126
    return True
127
 
127
 
128
def parse_config(fname, ask_names):
128
def parse_config(fname, ask_names):
129
    "Parse configuration file"
129
    "Parse configuration file"
130
   
130
   
131
    inf = file(fname, 'r')
131
    inf = file(fname, 'r')
132
   
132
   
133
    name = ''
133
    name = ''
134
    choices = []
134
    choices = []
135
   
135
   
136
    for line in inf:
136
    for line in inf:
137
       
137
       
138
        if (line.startswith('!')):
138
        if (line.startswith('!')):
139
            # Ask a question
139
            # Ask a question
140
            res = re.search(r'!\s*(?:\[(.*?)\])?\s*([^\s]+)\s*\((.*)\)\s*$', line)
140
            res = re.search(r'!\s*(?:\[(.*?)\])?\s*([^\s]+)\s*\((.*)\)\s*$', line)
141
           
141
           
142
            if (not res):
142
            if (not res):
143
                raise RuntimeError("Weird line: %s" % line)
143
                raise RuntimeError("Weird line: %s" % line)
144
           
144
           
145
            cond = res.group(1)
145
            cond = res.group(1)
146
            varname = res.group(2)
146
            varname = res.group(2)
147
            vartype = res.group(3)
147
            vartype = res.group(3)
148
           
148
           
149
            ask_names.append((varname, vartype, name, choices, cond))
149
            ask_names.append((varname, vartype, name, choices, cond))
150
            name = ''
150
            name = ''
151
            choices = []
151
            choices = []
152
            continue
152
            continue
153
       
153
       
154
        if (line.startswith('@')):
154
        if (line.startswith('@')):
155
            # Add new line into the 'choices' array
155
            # Add new line into the 'choices' array
156
            res = re.match(r'@\s*(?:\[(.*?)\])?\s*"(.*?)"\s*(.*)$', line)
156
            res = re.match(r'@\s*(?:\[(.*?)\])?\s*"(.*?)"\s*(.*)$', line)
157
           
157
           
158
            if not res:
158
            if not res:
159
                raise RuntimeError("Bad line: %s" % line)
159
                raise RuntimeError("Bad line: %s" % line)
160
           
160
           
161
            choices.append((res.group(2), res.group(3)))
161
            choices.append((res.group(2), res.group(3)))
162
            continue
162
            continue
163
       
163
       
164
        if (line.startswith('%')):
164
        if (line.startswith('%')):
165
            # Name of the option
165
            # Name of the option
166
            name = line[1:].strip()
166
            name = line[1:].strip()
167
            continue
167
            continue
168
       
168
       
169
        if ((line.startswith('#')) or (line == '\n')):
169
        if ((line.startswith('#')) or (line == '\n')):
170
            # Comment or empty line
170
            # Comment or empty line
171
            continue
171
            continue
172
       
172
       
173
       
173
       
174
        raise RuntimeError("Unknown syntax: %s" % line)
174
        raise RuntimeError("Unknown syntax: %s" % line)
175
   
175
   
176
    inf.close()
176
    inf.close()
177
 
177
 
178
def yes_no(default):
178
def yes_no(default):
179
    "Return '*' if yes, ' ' if no"
179
    "Return '*' if yes, ' ' if no"
180
   
180
   
181
    if (default == 'y'):
181
    if (default == 'y'):
182
        return '*'
182
        return '*'
183
   
183
   
184
    return ' '
184
    return ' '
185
 
185
 
186
def subchoice(screen, name, choices, default):
186
def subchoice(screen, name, choices, default):
187
    "Return choice of choices"
187
    "Return choice of choices"
188
   
188
   
189
    maxkey = 0
189
    maxkey = 0
190
    for key, val in choices:
190
    for key, val in choices:
191
        length = len(key)
191
        length = len(key)
192
        if (length > maxkey):
192
        if (length > maxkey):
193
            maxkey = length
193
            maxkey = length
194
   
194
   
195
    options = []
195
    options = []
196
    position = None
196
    position = None
197
    cnt = 0
197
    cnt = 0
198
    for key, val in choices:
198
    for key, val in choices:
199
        if ((default) and (key == default)):
199
        if ((default) and (key == default)):
200
            position = cnt
200
            position = cnt
201
       
201
       
202
        options.append(" %-*s  %s " % (maxkey, key, val))
202
        options.append(" %-*s  %s " % (maxkey, key, val))
203
        cnt += 1
203
        cnt += 1
204
   
204
   
205
    (button, value) = xtui.choice_window(screen, name, 'Choose value', options, position)
205
    (button, value) = xtui.choice_window(screen, name, 'Choose value', options, position)
206
   
206
   
207
    if (button == 'cancel'):
207
    if (button == 'cancel'):
208
        return None
208
        return None
209
   
209
   
210
    return choices[value][0]
210
    return choices[value][0]
211
 
211
 
212
def check_choices(defaults, ask_names):
212
def check_choices(defaults, ask_names):
213
    "Check whether all accessible variables have a default"
213
    "Check whether all accessible variables have a default"
214
   
214
   
215
    for varname, vartype, name, choices, cond in ask_names:
215
    for varname, vartype, name, choices, cond in ask_names:
216
        if ((cond) and (not check_condition(cond, defaults, ask_names))):
216
        if ((cond) and (not check_condition(cond, defaults, ask_names))):
217
            continue
217
            continue
218
       
218
       
219
        if (not defaults.has_key(varname)):
219
        if (not defaults.has_key(varname)):
220
            return False
220
            return False
221
   
221
   
222
    return True
222
    return True
223
 
223
 
224
def create_output(mkname, mcname, dfname, defaults, ask_names):
224
def create_output(mkname, mcname, dfname, defaults, ask_names):
225
    "Create output configuration"
225
    "Create output configuration"
226
   
226
   
227
    revision = commands.getoutput('svnversion . 2> /dev/null')
227
    revision = commands.getoutput('svnversion . 2> /dev/null')
228
    timestamp = commands.getoutput('date "+%Y-%m-%d %H:%M:%S"')
228
    timestamp = commands.getoutput('date "+%Y-%m-%d %H:%M:%S"')
229
   
229
   
230
    outmk = file(mkname, 'w')
230
    outmk = file(mkname, 'w')
231
    outmc = file(mcname, 'w')
231
    outmc = file(mcname, 'w')
232
    outdf = file(dfname, 'w')
232
    outdf = file(dfname, 'w')
233
   
233
   
234
    outmk.write('#########################################\n')
234
    outmk.write('#########################################\n')
235
    outmk.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n')
235
    outmk.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n')
236
    outmk.write('#########################################\n\n')
236
    outmk.write('#########################################\n\n')
237
   
237
   
238
    outmc.write('/***************************************\n')
238
    outmc.write('/***************************************\n')
239
    outmc.write(' * AUTO-GENERATED FILE, DO NOT EDIT!!! *\n')
239
    outmc.write(' * AUTO-GENERATED FILE, DO NOT EDIT!!! *\n')
240
    outmc.write(' ***************************************/\n\n')
240
    outmc.write(' ***************************************/\n\n')
241
   
241
   
242
    outdf.write('#########################################\n')
242
    outdf.write('#########################################\n')
243
    outdf.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n')
243
    outdf.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n')
244
    outdf.write('#########################################\n\n')
244
    outdf.write('#########################################\n\n')
245
    outdf.write('CONFIG_DEFS =')
245
    outdf.write('CONFIG_DEFS =')
246
   
246
   
247
    for varname, vartype, name, choices, cond in ask_names:
247
    for varname, vartype, name, choices, cond in ask_names:
248
        if ((cond) and (not check_condition(cond, defaults, ask_names))):
248
        if ((cond) and (not check_condition(cond, defaults, ask_names))):
249
            continue
249
            continue
250
       
250
       
251
        if (not defaults.has_key(varname)):
251
        if (not defaults.has_key(varname)):
252
            default = ''
252
            default = ''
253
        else:
253
        else:
254
            default = defaults[varname]
254
            default = defaults[varname]
255
            if (default == '*'):
255
            if (default == '*'):
256
                default = 'y'
256
                default = 'y'
257
       
257
       
258
        outmk.write('# %s\n%s = %s\n\n' % (name, varname, default))
258
        outmk.write('# %s\n%s = %s\n\n' % (name, varname, default))
259
       
259
       
260
        if ((vartype == "y") or (vartype == "y/n") or (vartype == "n/y")):
260
        if ((vartype == "y") or (vartype == "n") or (vartype == "y/n") or (vartype == "n/y")):
261
            if (default == "y"):
261
            if (default == "y"):
262
                outmc.write('/* %s */\n#define %s\n\n' % (name, varname))
262
                outmc.write('/* %s */\n#define %s\n\n' % (name, varname))
263
                outdf.write(' -D%s' % varname)
263
                outdf.write(' -D%s' % varname)
264
        else:
264
        else:
265
            outmc.write('/* %s */\n#define %s %s\n#define %s_%s\n\n' % (name, varname, default, varname, default))
265
            outmc.write('/* %s */\n#define %s %s\n#define %s_%s\n\n' % (name, varname, default, varname, default))
266
            outdf.write(' -D%s=%s -D%s_%s' % (varname, default, varname, default))
266
            outdf.write(' -D%s=%s -D%s_%s' % (varname, default, varname, default))
267
   
267
   
268
    outmk.write('REVISION = %s\n' % revision)
268
    outmk.write('REVISION = %s\n' % revision)
269
    outmk.write('TIMESTAMP = %s\n' % timestamp)
269
    outmk.write('TIMESTAMP = %s\n' % timestamp)
270
   
270
   
271
    outmc.write('#define REVISION %s\n' % revision)
271
    outmc.write('#define REVISION %s\n' % revision)
272
    outmc.write('#define TIMESTAMP %s\n' % timestamp)
272
    outmc.write('#define TIMESTAMP %s\n' % timestamp)
273
   
273
   
274
    outdf.write(' "-DREVISION=%s" "-DTIMESTAMP=%s"\n' % (revision, timestamp))
274
    outdf.write(' "-DREVISION=%s" "-DTIMESTAMP=%s"\n' % (revision, timestamp))
275
   
275
   
276
    outmk.close()
276
    outmk.close()
277
    outmc.close()
277
    outmc.close()
278
    outdf.close()
278
    outdf.close()
279
 
279
 
280
def sorted_dir(root):
280
def sorted_dir(root):
281
    list = os.listdir(root)
281
    list = os.listdir(root)
282
    list.sort()
282
    list.sort()
283
    return list
283
    return list
284
 
284
 
285
def read_preconfigured(root, fname, screen, defaults):
285
def read_preconfigured(root, fname, screen, defaults):
286
    options = []
286
    options = []
287
    opt2path = {}
287
    opt2path = {}
288
    cnt = 0
288
    cnt = 0
289
   
289
   
290
    # Look for profiles
290
    # Look for profiles
291
    for name in sorted_dir(root):
291
    for name in sorted_dir(root):
292
        path = os.path.join(root, name)
292
        path = os.path.join(root, name)
293
        canon = os.path.join(path, fname)
293
        canon = os.path.join(path, fname)
294
       
294
       
295
        if ((os.path.isdir(path)) and (os.path.exists(canon)) and (os.path.isfile(canon))):
295
        if ((os.path.isdir(path)) and (os.path.exists(canon)) and (os.path.isfile(canon))):
296
            subprofile = False
296
            subprofile = False
297
           
297
           
298
            # Look for subprofiles
298
            # Look for subprofiles
299
            for subname in sorted_dir(path):
299
            for subname in sorted_dir(path):
300
                subpath = os.path.join(path, subname)
300
                subpath = os.path.join(path, subname)
301
                subcanon = os.path.join(subpath, fname)
301
                subcanon = os.path.join(subpath, fname)
302
               
302
               
303
                if ((os.path.isdir(subpath)) and (os.path.exists(subcanon)) and (os.path.isfile(subcanon))):
303
                if ((os.path.isdir(subpath)) and (os.path.exists(subcanon)) and (os.path.isfile(subcanon))):
304
                    subprofile = True
304
                    subprofile = True
305
                    options.append("%s (%s)" % (name, subname))
305
                    options.append("%s (%s)" % (name, subname))
306
                    opt2path[cnt] = (canon, subcanon)
306
                    opt2path[cnt] = (canon, subcanon)
307
                    cnt += 1
307
                    cnt += 1
308
           
308
           
309
            if (not subprofile):
309
            if (not subprofile):
310
                options.append(name)
310
                options.append(name)
311
                opt2path[cnt] = (canon, None)
311
                opt2path[cnt] = (canon, None)
312
                cnt += 1
312
                cnt += 1
313
   
313
   
314
    (button, value) = xtui.choice_window(screen, 'Load preconfigured defaults', 'Choose configuration profile', options, None)
314
    (button, value) = xtui.choice_window(screen, 'Load preconfigured defaults', 'Choose configuration profile', options, None)
315
   
315
   
316
    if (button == 'cancel'):
316
    if (button == 'cancel'):
317
        return None
317
        return None
318
   
318
   
319
    read_defaults(opt2path[value][0], defaults)
319
    read_defaults(opt2path[value][0], defaults)
320
    if (opt2path[value][1] != None):
320
    if (opt2path[value][1] != None):
321
        read_defaults(opt2path[value][1], defaults)
321
        read_defaults(opt2path[value][1], defaults)
322
 
322
 
323
def main():
323
def main():
324
    defaults = {}
324
    defaults = {}
325
    ask_names = []
325
    ask_names = []
326
   
326
   
327
    # Parse configuration file
327
    # Parse configuration file
328
    parse_config(INPUT, ask_names)
328
    parse_config(INPUT, ask_names)
329
   
329
   
330
    # Read defaults from previous run
330
    # Read defaults from previous run
331
    if os.path.exists(MAKEFILE):
331
    if os.path.exists(MAKEFILE):
332
        read_defaults(MAKEFILE, defaults)
332
        read_defaults(MAKEFILE, defaults)
333
   
333
   
334
    # Default mode: only check defaults and regenerate configuration
334
    # Default mode: only check defaults and regenerate configuration
335
    if ((len(sys.argv) >= 3) and (sys.argv[2] == 'default')):
335
    if ((len(sys.argv) >= 3) and (sys.argv[2] == 'default')):
336
        if (check_choices(defaults, ask_names)):
336
        if (check_choices(defaults, ask_names)):
337
            create_output(MAKEFILE, MACROS, DEFS, defaults, ask_names)
337
            create_output(MAKEFILE, MACROS, DEFS, defaults, ask_names)
338
            return 0
338
            return 0
339
   
339
   
340
    # Check mode: only check defaults
340
    # Check mode: only check defaults
341
    if ((len(sys.argv) >= 3) and (sys.argv[2] == 'check')):
341
    if ((len(sys.argv) >= 3) and (sys.argv[2] == 'check')):
342
        if (check_choices(defaults, ask_names)):
342
        if (check_choices(defaults, ask_names)):
343
            return 0
343
            return 0
344
        return 1
344
        return 1
345
   
345
   
346
    screen = xtui.screen_init()
346
    screen = xtui.screen_init()
347
    try:
347
    try:
348
        selname = None
348
        selname = None
349
        position = None
349
        position = None
350
        while True:
350
        while True:
351
           
351
           
352
            # Cancel out all defaults which have to be deduced
352
            # Cancel out all defaults which have to be deduced
353
            for varname, vartype, name, choices, cond in ask_names:
353
            for varname, vartype, name, choices, cond in ask_names:
354
                if ((vartype == 'y') and (defaults.has_key(varname)) and (defaults[varname] == '*')):
354
                if ((vartype == 'y') and (defaults.has_key(varname)) and (defaults[varname] == '*')):
355
                    defaults[varname] = None
355
                    defaults[varname] = None
356
           
356
           
357
            options = []
357
            options = []
358
            opt2row = {}
358
            opt2row = {}
359
            cnt = 1
359
            cnt = 1
360
           
360
           
361
            options.append("  --- Load preconfigured defaults ... ")
361
            options.append("  --- Load preconfigured defaults ... ")
362
           
362
           
363
            for varname, vartype, name, choices, cond in ask_names:
363
            for varname, vartype, name, choices, cond in ask_names:
364
               
364
               
365
                if ((cond) and (not check_condition(cond, defaults, ask_names))):
365
                if ((cond) and (not check_condition(cond, defaults, ask_names))):
366
                    continue
366
                    continue
367
               
367
               
368
                if (varname == selname):
368
                if (varname == selname):
369
                    position = cnt
369
                    position = cnt
370
               
370
               
371
                if (not defaults.has_key(varname)):
371
                if (not defaults.has_key(varname)):
372
                    default = None
372
                    default = None
373
                else:
373
                else:
374
                    default = defaults[varname]
374
                    default = defaults[varname]
375
               
375
               
376
                if (vartype == 'choice'):
376
                if (vartype == 'choice'):
377
                    # Check if the default is an acceptable value
377
                    # Check if the default is an acceptable value
378
                    if ((default) and (not default in [choice[0] for choice in choices])):
378
                    if ((default) and (not default in [choice[0] for choice in choices])):
379
                        default = None
379
                        default = None
380
                        defaults.pop(varname)
380
                        defaults.pop(varname)
381
                   
381
                   
382
                    # If there is just one option, use it
382
                    # If there is just one option, use it
383
                    if (len(choices) == 1):
383
                    if (len(choices) == 1):
384
                        defaults[varname] = choices[0][0]
384
                        defaults[varname] = choices[0][0]
385
                        continue
385
                        continue
386
                   
386
                   
387
                    if (default == None):
387
                    if (default == None):
388
                        options.append("?     %s --> " % name)
388
                        options.append("?     %s --> " % name)
389
                    else:
389
                    else:
390
                        options.append("      %s [%s] --> " % (name, default))
390
                        options.append("      %s [%s] --> " % (name, default))
391
                elif (vartype == 'y'):
391
                elif (vartype == 'y'):
392
                    defaults[varname] = '*'
392
                    defaults[varname] = '*'
393
                    continue
393
                    continue
394
                elif (vartype == 'n'):
394
                elif (vartype == 'n'):
395
                    defaults[varname] = 'n'
395
                    defaults[varname] = 'n'
396
                    continue
396
                    continue
397
                elif (vartype == 'y/n'):
397
                elif (vartype == 'y/n'):
398
                    if (default == None):
398
                    if (default == None):
399
                        default = 'y'
399
                        default = 'y'
400
                        defaults[varname] = default
400
                        defaults[varname] = default
401
                    options.append("  <%s> %s " % (yes_no(default), name))
401
                    options.append("  <%s> %s " % (yes_no(default), name))
402
                elif (vartype == 'n/y'):
402
                elif (vartype == 'n/y'):
403
                    if (default == None):
403
                    if (default == None):
404
                        default = 'n'
404
                        default = 'n'
405
                        defaults[varname] = default
405
                        defaults[varname] = default
406
                    options.append("  <%s> %s " % (yes_no(default), name))
406
                    options.append("  <%s> %s " % (yes_no(default), name))
407
                else:
407
                else:
408
                    raise RuntimeError("Unknown variable type: %s" % vartype)
408
                    raise RuntimeError("Unknown variable type: %s" % vartype)
409
               
409
               
410
                opt2row[cnt] = (varname, vartype, name, choices)
410
                opt2row[cnt] = (varname, vartype, name, choices)
411
               
411
               
412
                cnt += 1
412
                cnt += 1
413
           
413
           
414
            if (position >= options):
414
            if (position >= options):
415
                position = None
415
                position = None
416
           
416
           
417
            (button, value) = xtui.choice_window(screen, 'HelenOS configuration', 'Choose configuration option', options, position)
417
            (button, value) = xtui.choice_window(screen, 'HelenOS configuration', 'Choose configuration option', options, position)
418
           
418
           
419
            if (button == 'cancel'):
419
            if (button == 'cancel'):
420
                return 'Configuration canceled'
420
                return 'Configuration canceled'
421
           
421
           
422
            if (button == 'done'):
422
            if (button == 'done'):
423
                if (check_choices(defaults, ask_names)):
423
                if (check_choices(defaults, ask_names)):
424
                    break
424
                    break
425
                else:
425
                else:
426
                    xtui.error_dialog(screen, 'Error', 'Some options have still undefined values. These options are marked with the "?" sign.')
426
                    xtui.error_dialog(screen, 'Error', 'Some options have still undefined values. These options are marked with the "?" sign.')
427
                    continue
427
                    continue
428
           
428
           
429
            if (value == 0):
429
            if (value == 0):
430
                read_preconfigured(PRECONF, MAKEFILE, screen, defaults)
430
                read_preconfigured(PRECONF, MAKEFILE, screen, defaults)
431
                position = 1
431
                position = 1
432
                continue
432
                continue
433
           
433
           
434
            position = None
434
            position = None
435
            if (not opt2row.has_key(value)):
435
            if (not opt2row.has_key(value)):
436
                raise RuntimeError("Error selecting value: %s" % value)
436
                raise RuntimeError("Error selecting value: %s" % value)
437
           
437
           
438
            (selname, seltype, name, choices) = opt2row[value]
438
            (selname, seltype, name, choices) = opt2row[value]
439
           
439
           
440
            if (not defaults.has_key(selname)):
440
            if (not defaults.has_key(selname)):
441
                    default = None
441
                    default = None
442
            else:
442
            else:
443
                default = defaults[selname]
443
                default = defaults[selname]
444
           
444
           
445
            if (seltype == 'choice'):
445
            if (seltype == 'choice'):
446
                defaults[selname] = subchoice(screen, name, choices, default)
446
                defaults[selname] = subchoice(screen, name, choices, default)
447
            elif ((seltype == 'y/n') or (seltype == 'n/y')):
447
            elif ((seltype == 'y/n') or (seltype == 'n/y')):
448
                if (defaults[selname] == 'y'):
448
                if (defaults[selname] == 'y'):
449
                    defaults[selname] = 'n'
449
                    defaults[selname] = 'n'
450
                else:
450
                else:
451
                    defaults[selname] = 'y'
451
                    defaults[selname] = 'y'
452
    finally:
452
    finally:
453
        xtui.screen_done(screen)
453
        xtui.screen_done(screen)
454
   
454
   
455
    create_output(MAKEFILE, MACROS, DEFS, defaults, ask_names)
455
    create_output(MAKEFILE, MACROS, DEFS, defaults, ask_names)
456
    return 0
456
    return 0
457
 
457
 
458
if __name__ == '__main__':
458
if __name__ == '__main__':
459
    sys.exit(main())
459
    sys.exit(main())
460
 
460