Subversion Repositories HelenOS

Rev

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

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