Subversion Repositories HelenOS

Rev

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

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