Subversion Repositories HelenOS

Rev

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

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