Subversion Repositories HelenOS

Rev

Rev 3107 | Rev 4341 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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