Subversion Repositories HelenOS

Rev

Rev 3017 | Rev 3804 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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