source: rtems-tools/rtemstoolkit/config.py @ de1beea

4.10
Last change on this file since de1beea was de1beea, checked in by Chris Johns <chrisj@…>, on Feb 19, 2016 at 12:26:51 AM

Disable installing PYO and PYC. Fix install paths.

Installing PYO and PYC does not work so disable this. Move the
Python check to the top level and have a single place.

Fix the install paths a revert the 'from . import' changes. This
is resolved by installing into the correct paths.

  • Property mode set to 100644
File size: 31.5 KB
Line 
1#
2# RTEMS Tools Project (http://www.rtems.org/)
3# Copyright 2010-2014 Chris Johns (chrisj@rtems.org)
4# All rights reserved.
5#
6# This file is part of the RTEMS Tools package in 'rtems-tools'.
7#
8# Redistribution and use in source and binary forms, with or without
9# modification, are permitted provided that the following conditions are met:
10#
11# 1. Redistributions of source code must retain the above copyright notice,
12# this list of conditions and the following disclaimer.
13#
14# 2. Redistributions in binary form must reproduce the above copyright notice,
15# this list of conditions and the following disclaimer in the documentation
16# and/or other materials provided with the distribution.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28# POSSIBILITY OF SUCH DAMAGE.
29#
30
31#
32# This code is based on a tool I wrote to parse RPM spec files in the RTEMS
33# project. This is now a configuration file format that has moved away from the
34# spec file format to support the specific needs of cross-compiling GCC. This
35# module parses a configuration file into Python data types that can be used by
36# other software modules.
37#
38
39import copy
40import os
41import re
42import sys
43
44import error
45import execute
46import log
47import options
48import path
49
50try:
51    import error
52    import execute
53    import log
54    import options
55    import path
56except KeyboardInterrupt:
57    print('user terminated')
58    sys.exit(1)
59except:
60    print('error: unknown application load error')
61    sys.exit(1)
62
63def _check_bool(value):
64    if value.isdigit():
65        if int(value) == 0:
66            istrue = False
67        else:
68            istrue = True
69    else:
70        istrue = None
71    return istrue
72
73class file(object):
74    """Parse a config file."""
75
76    def __init__(self, name, opts, macros = None, directives = None, ignores = None):
77        self.opts = opts
78        if macros is None:
79            self.macros = opts.defaults
80        else:
81            self.macros = macros
82        self.init_name = name
83        self.directives = ['%include']
84        if directives:
85            self.directives += directives
86        self.ignores = ignores
87        log.trace('config: %s' % (name))
88        self.disable_macro_reassign = False
89        self.configpath = []
90        self.wss = re.compile(r'\s+')
91        self.tags = re.compile(r':+')
92        self.sf = re.compile(r'%\([^\)]+\)')
93        for arg in self.opts.args:
94            if arg.startswith('--with-') or arg.startswith('--without-'):
95                label = arg[2:].lower().replace('-', '_')
96                self.macros.define(label)
97        self._includes = []
98        self.load_depth = 0
99
100    def __del__(self):
101        pass
102
103    def __str__(self):
104
105        def _dict(dd):
106            s = ''
107            ddl = dd.keys()
108            ddl.sort()
109            for d in ddl:
110                s += '  ' + d + ': ' + dd[d] + '\n'
111            return s
112
113        s = 'config: %s' % ('.'.join(self.configpath)) + \
114            '\n' + str(self.opts) + \
115            '\nlines parsed: %d' % (self.lc) + \
116            '\nname: ' + self.name + \
117            '\nmacros:\n' + str(self.macros)
118        return s
119
120    def _name_line_msg(self,  msg):
121        return '%s:%d: %s' % (path.basename(self.init_name), self.lc,  msg)
122
123    def _output(self, text):
124        if not self.opts.quiet():
125            log.output(text)
126
127    def _error(self, msg):
128        err = 'error: %s' % (self._name_line_msg(msg))
129        log.stderr(err)
130        log.output(err)
131        self.in_error = True
132        if not self.opts.dry_run():
133            log.stderr('warning: switched to dry run due to errors')
134            self.opts.set_dry_run()
135
136    def _label(self, name):
137        if name.startswith('%{') and name[-1] is '}':
138            return name
139        return '%{' + name.lower() + '}'
140
141    def _macro_split(self, s):
142        '''Split the string (s) up by macros. Only split on the
143           outter level. Nested levels will need to split with futher calls.'''
144        trace_me = False
145        if trace_me:
146            print('------------------------------------------------------')
147        macros = []
148        nesting = []
149        has_braces = False
150        c = 0
151        while c < len(s):
152            if trace_me:
153                print('ms:', c, '"' + s[c:] + '"', has_braces, len(nesting), nesting)
154            #
155            # We need to watch for shell type variables or the form '${var}' because
156            # they can upset the brace matching.
157            #
158            if s[c] == '%' or s[c] == '$':
159                start = s[c]
160                c += 1
161                if c == len(s):
162                    continue
163                #
164                # Do we have '%%' or '%(' or '$%' or '$(' or not '${' ?
165                #
166                if s[c] == '%' or s[c] == '(' or (start == '$' and s[c] != '{'):
167                    continue
168                elif not s[c].isspace():
169                    #
170                    # If this is a shell macro and we are at the outter
171                    # level or is '$var' forget it and move on.
172                    #
173                    if start == '$' and (s[c] != '{' or len(nesting) == 0):
174                        continue
175                    if s[c] == '{':
176                        this_has_braces = True
177                    else:
178                        this_has_braces = False
179                    nesting.append((c - 1, has_braces))
180                    has_braces = this_has_braces
181            elif len(nesting) > 0:
182                if s[c] == '}' or (s[c].isspace() and not has_braces):
183                    #
184                    # Can have '%{?test: something %more}' where the
185                    # nested %more ends with the '}' which also ends
186                    # the outter macro.
187                    #
188                    if not has_braces:
189                        if s[c] == '}':
190                            macro_start, has_braces = nesting[len(nesting) - 1]
191                            nesting = nesting[:-1]
192                            if len(nesting) == 0:
193                                macros.append(s[macro_start:c].strip())
194                    if len(nesting) > 0:
195                        macro_start, has_braces = nesting[len(nesting) - 1]
196                        nesting = nesting[:-1]
197                        if len(nesting) == 0:
198                            macros.append(s[macro_start:c + 1].strip())
199            c += 1
200        if trace_me:
201            print('ms:', macros)
202        if trace_me:
203            print('-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=')
204        return macros
205
206    def _shell(self, line):
207        sl = self.sf.findall(line)
208        if len(sl):
209            e = execute.capture_execution()
210            for s in sl:
211                if options.host_windows:
212                    cmd = '%s -c "%s"' % (self.macros.expand('%{__sh}'), s[2:-1])
213                else:
214                    cmd = s[2:-1]
215                exit_code, proc, output = e.shell(cmd)
216                if exit_code == 0:
217                    line = line.replace(s, output)
218                else:
219                    raise error.general('shell macro failed: %s:%d: %s' % (s, exit_code, output))
220        return line
221
222    def _expand(self, s):
223        expand_count = 0
224        expanded = True
225        while expanded:
226            expand_count += 1
227            if expand_count > 500:
228                raise error.general('macro expand looping: %s' % (s))
229            expanded = False
230            ms = self._macro_split(s)
231            for m in ms:
232                mn = m
233                #
234                # A macro can be '%{macro}' or '%macro'. Turn the later into
235                # the former.
236                #
237                show_warning = True
238                if mn[1] != '{':
239                    if self.ignores is not None:
240                        for r in self.ignores:
241                            if r.match(mn) is not None:
242                                mn = None
243                                break
244                        else:
245                            mn = self._label(mn[1:])
246                            show_warning = False
247                    else:
248                        mn = self._label(mn[1:])
249                        show_warning = False
250                elif m.startswith('%{expand'):
251                    colon = m.find(':')
252                    if colon < 8:
253                        log.warning('malformed expand macro, no colon found')
254                    else:
255                        e = self._expand(m[colon + 1:-1].strip())
256                        s = s.replace(m, e)
257                        expanded = True
258                        mn = None
259                elif m.startswith('%{with '):
260                    #
261                    # Change the ' ' to '_' because the macros have no spaces.
262                    #
263                    n = self._label('with_' + m[7:-1].strip())
264                    if n in self.macros:
265                        s = s.replace(m, '1')
266                    else:
267                        s = s.replace(m, '0')
268                    expanded = True
269                    mn = None
270                elif m.startswith('%{echo'):
271                    if not m.endswith('}'):
272                        log.warning("malformed conditional macro '%s'" % (m))
273                        mn = None
274                    else:
275                        e = self._expand(m[6:-1].strip())
276                        log.output('%s' % (self._name_line_msg(e)))
277                        s = ''
278                        expanded = True
279                        mn = None
280                elif m.startswith('%{defined'):
281                    n = self._label(m[9:-1].strip())
282                    if n in self.macros:
283                        s = s.replace(m, '1')
284                    else:
285                        s = s.replace(m, '0')
286                    expanded = True
287                    mn = None
288                elif m.startswith('%{?') or m.startswith('%{!?'):
289                    if m[2] == '!':
290                        start = 4
291                    else:
292                        start = 3
293                    colon = m[start:].find(':')
294                    if colon < 0:
295                        if not m.endswith('}'):
296                            log.warning("malformed conditional macro '%s'" % (m))
297                            mn = None
298                        else:
299                            mn = self._label(m[start:-1])
300                    else:
301                        mn = self._label(m[start:start + colon])
302                    if mn:
303                        if m.startswith('%{?'):
304                            istrue = False
305                            if mn in self.macros:
306                                # If defined and 0 then it is false.
307                                istrue = _check_bool(self.macros[mn])
308                                if istrue is None:
309                                    istrue = True
310                            if colon >= 0 and istrue:
311                                s = s.replace(m, m[start + colon + 1:-1])
312                                expanded = True
313                                mn = None
314                            elif not istrue:
315                                mn = '%{nil}'
316                        else:
317                            isfalse = True
318                            if mn in self.macros:
319                                istrue = _check_bool(self.macros[mn])
320                                if istrue is None or istrue == True:
321                                    isfalse = False
322                            if colon >= 0 and isfalse:
323                                s = s.replace(m, m[start + colon + 1:-1])
324                                expanded = True
325                                mn = None
326                            else:
327                                mn = '%{nil}'
328                if mn:
329                    if mn.lower() in self.macros:
330                        s = s.replace(m, self.macros[mn.lower()])
331                        expanded = True
332                    elif show_warning:
333                        self._error("macro '%s' not found" % (mn))
334        return self._shell(s)
335
336    def _disable(self, config, ls):
337        if len(ls) != 2:
338            log.warning('invalid disable statement')
339        else:
340            if ls[1] == 'select':
341                self.macros.lock_read_map()
342                log.trace('config: %s: _disable_select: %s' % (self.init_name, ls[1]))
343            else:
344                log.warning('invalid disable statement: %s' % (ls[1]))
345
346    def _select(self, config, ls):
347        if len(ls) != 2:
348            log.warning('invalid select statement')
349        else:
350            r = self.macros.set_read_map(ls[1])
351            log.trace('config: %s: _select: %s %s %r' % \
352                          (self.init_name, r, ls[1], self.macros.maps()))
353
354    def _define(self, config, ls):
355        if len(ls) <= 1:
356            log.warning('invalid macro definition')
357        else:
358            d = self._label(ls[1])
359            if self.disable_macro_reassign:
360                if (d not in self.macros) or \
361                        (d in self.macros and len(self.macros[d]) == 0):
362                    if len(ls) == 2:
363                        self.macros[d] = '1'
364                    else:
365                        self.macros[d] = ' '.join([f.strip() for f in ls[2:]])
366                else:
367                    log.warning("macro '%s' already defined" % (d))
368            else:
369                if len(ls) == 2:
370                    self.macros[d] = '1'
371                else:
372                    self.macros[d] = ' '.join([f.strip() for f in ls[2:]])
373
374    def _undefine(self, config, ls):
375        if len(ls) <= 1:
376            log.warning('invalid macro definition')
377        else:
378            mn = self._label(ls[1])
379            if mn in self.macros:
380                del self.macros[mn]
381            else:
382                log.warning("macro '%s' not defined" % (mn))
383
384    def _ifs(self, config, ls, label, iftrue, isvalid, dir, info):
385        in_iftrue = True
386        data = []
387        while True:
388            if isvalid and \
389                    ((iftrue and in_iftrue) or (not iftrue and not in_iftrue)):
390                this_isvalid = True
391            else:
392                this_isvalid = False
393            r = self._parse(config, dir, info, roc = True, isvalid = this_isvalid)
394            if r[0] == 'control':
395                if r[1] == '%end':
396                    self._error(label + ' without %endif')
397                    raise error.general('terminating build')
398                if r[1] == '%endif':
399                    log.trace('config: %s: _ifs: %s %s' % (self.init_name, r[1], this_isvalid))
400                    return data
401                if r[1] == '%else':
402                    in_iftrue = False
403            elif r[0] == 'directive':
404                if this_isvalid:
405                    if r[1] == '%include':
406                        self.load(r[2][0])
407                        continue
408                    dir, info, data = self._process_directive(r, dir, info, data)
409            elif r[0] == 'data':
410                if this_isvalid:
411                    dir, info, data = self._process_data(r, dir, info, data)
412            else:
413                dir, info, data = self._process_block(r, dir, info, data)
414
415        # @note is a directive extend missing
416
417    def _if(self, config, ls, isvalid, dir, info, invert = False):
418
419        def add(x, y):
420            return x + ' ' + str(y)
421
422        istrue = False
423        if isvalid:
424            if len(ls) == 2:
425                s = ls[1]
426            else:
427                s = (ls[1] + ' ' + ls[2])
428            ifls = s.split()
429            if len(ifls) == 1:
430                #
431                # Check if '%if %{x} == %{nil}' has both parts as nothing
432                # which means '%if ==' is always True and '%if !=' is always false.
433                #
434                if ifls[0] == '==':
435                    istrue = True
436                elif ifls[0] == '!=':
437                    istrue = False
438                else:
439                    istrue = _check_bool(ifls[0])
440                    if istrue == None:
441                        self._error('invalid if bool value: ' + reduce(add, ls, ''))
442                        istrue = False
443            elif len(ifls) == 2:
444                if ifls[0] == '!':
445                    istrue = _check_bool(ifls[1])
446                    if istrue == None:
447                        self._error('invalid if bool value: ' + reduce(add, ls, ''))
448                        istrue = False
449                    else:
450                        istrue = not istrue
451                else:
452                    #
453                    # Check is something is being checked against empty,
454                    #   ie '%if %{x} == %{nil}'
455                    # The logic is 'something == nothing' is False and
456                    # 'something != nothing' is True.
457                    #
458                    if ifls[1] == '==':
459                        istrue = False
460                    elif  ifls[1] == '!=':
461                        istrue = True
462                    else:
463                        self._error('invalid if bool operator: ' + reduce(add, ls, ''))
464            elif len(ifls) == 3:
465                if ifls[1] == '==':
466                    if ifls[0] == ifls[2]:
467                        istrue = True
468                    else:
469                        istrue = False
470                elif ifls[1] == '!=' or ifls[1] == '=!':
471                    if ifls[0] != ifls[2]:
472                        istrue = True
473                    else:
474                        istrue = False
475                elif ifls[1] == '>':
476                    if ifls[0] > ifls[2]:
477                        istrue = True
478                    else:
479                        istrue = False
480                elif ifls[1] == '>=' or ifls[1] == '=>':
481                    if ifls[0] >= ifls[2]:
482                        istrue = True
483                    else:
484                        istrue = False
485                elif ifls[1] == '<=' or ifls[1] == '=<':
486                    if ifls[0] <= ifls[2]:
487                        istrue = True
488                    else:
489                        istrue = False
490                elif ifls[1] == '<':
491                    if ifls[0] < ifls[2]:
492                        istrue = True
493                    else:
494                        istrue = False
495                else:
496                    self._error('invalid %if operator: ' + reduce(add, ls, ''))
497            else:
498                self._error('malformed if: ' + reduce(add, ls, ''))
499            if invert:
500                istrue = not istrue
501            log.trace('config: %s: _if:  %s %s' % (self.init_name, ifls, str(istrue)))
502        return self._ifs(config, ls, '%if', istrue, isvalid, dir, info)
503
504    def _ifos(self, config, ls, isvalid, dir, info):
505        isos = False
506        if isvalid:
507            os = self.define('_os')
508            for l in ls:
509                if l in os:
510                    isos = True
511                    break
512        return self._ifs(config, ls, '%ifos', isos, isvalid, dir, info)
513
514    def _ifarch(self, config, positive, ls, isvalid, dir, info):
515        isarch = False
516        if isvalid:
517            arch = self.define('_arch')
518            for l in ls:
519                if l in arch:
520                    isarch = True
521                    break
522        if not positive:
523            isarch = not isarch
524        return self._ifs(config, ls, '%ifarch', isarch, isvalid, dir, info)
525
526    def _parse(self, config, dir, info, roc = False, isvalid = True):
527        # roc = return on control
528
529        def _clean(line):
530            line = line[0:-1]
531            b = line.find('#')
532            if b >= 0:
533                line = line[1:b]
534            return line.strip()
535
536        #
537        # Need to add code to count matching '{' and '}' and if they
538        # do not match get the next line and add to the string until
539        # they match. This closes an opening '{' that is on another
540        # line.
541        #
542        for l in config:
543            self.lc += 1
544            l = _clean(l)
545            if len(l) == 0:
546                continue
547            log.trace('config: %s: %03d: %s %s' % \
548                          (self.init_name, self.lc, str(isvalid), l))
549            lo = l
550            if isvalid:
551                l = self._expand(l)
552            if len(l) == 0:
553                continue
554            if l[0] == '%':
555                ls = self.wss.split(l, 2)
556                los = self.wss.split(lo, 2)
557                if ls[0] == '%disable':
558                    if isvalid:
559                        self._disable(config, ls)
560                elif ls[0] == '%select':
561                    if isvalid:
562                        self._select(config, ls)
563                elif ls[0] == '%error':
564                    if isvalid:
565                        return ('data', ['%%error %s' % (self._name_line_msg(l[7:]))])
566                elif ls[0] == '%warning':
567                    if isvalid:
568                        return ('data', ['%%warning %s' % (self._name_line_msg(l[9:]))])
569                elif ls[0] == '%define' or ls[0] == '%global':
570                    if isvalid:
571                        self._define(config, ls)
572                elif ls[0] == '%undefine':
573                    if isvalid:
574                        self._undefine(config, ls)
575                elif ls[0] == '%if':
576                    d = self._if(config, ls, isvalid, dir, info)
577                    if len(d):
578                        log.trace('config: %s: %%if: %s' % (self.init_name, d))
579                        return ('data', d)
580                elif ls[0] == '%ifn':
581                    d = self._if(config, ls, isvalid, dir, info, True)
582                    if len(d):
583                        log.trace('config: %s: %%ifn: %s' % (self.init_name, d))
584                        return ('data', d)
585                elif ls[0] == '%ifos':
586                    d = self._ifos(config, ls, isvalid, dir, info)
587                    if len(d):
588                        return ('data', d)
589                elif ls[0] == '%ifarch':
590                    d = self._ifarch(config, True, ls, isvalid, dir, info)
591                    if len(d):
592                        return ('data', d)
593                elif ls[0] == '%ifnarch':
594                    d = self._ifarch(config, False, ls, isvalid, dir, info)
595                    if len(d):
596                        return ('data', d)
597                elif ls[0] == '%endif':
598                    if roc:
599                        return ('control', '%endif', '%endif')
600                    log.warning("unexpected '" + ls[0] + "'")
601                elif ls[0] == '%else':
602                    if roc:
603                        return ('control', '%else', '%else')
604                    log.warning("unexpected '" + ls[0] + "'")
605                elif ls[0].startswith('%defattr'):
606                    return ('data', [l])
607                elif ls[0] == '%bcond_with':
608                    if isvalid:
609                        #
610                        # Check if already defined. Would be by the command line or
611                        # even a host specific default.
612                        #
613                        if self._label('with_' + ls[1]) not in self.macros:
614                            self._define(config, (ls[0], 'without_' + ls[1]))
615                elif ls[0] == '%bcond_without':
616                    if isvalid:
617                        if self._label('without_' + ls[1]) not in self.macros:
618                            self._define(config, (ls[0], 'with_' + ls[1]))
619                else:
620                    pt = self._parse_token(lo, los, l, ls)
621                    if pt is not None:
622                        return pt
623                    if self.ignores is not None:
624                        for r in self.ignores:
625                            if r.match(ls[0]) is not None:
626                                return ('data', [l])
627                    if isvalid:
628                        for d in self.directives:
629                            if ls[0].strip() == d:
630                                return ('directive', ls[0].strip(), ls[1:])
631                        log.warning("unknown directive: '" + ls[0] + "'")
632                        return ('data', [lo])
633            else:
634                return ('data', [lo])
635        return ('control', '%end', '%end')
636
637    def _parse_token(self, line, line_split, line_expanded, line_split_expanded):
638        return None
639
640    def _process_directive(self, results, directive, info, data):
641        new_data = []
642        if results[1] == '%description':
643            new_data = [' '.join(results[2])]
644        else:
645            directive, into, data = self._directive_filter(results, directive, info, data)
646        if directive and directive != results[1]:
647            self._directive_extend(directive, data)
648        directive = results[1]
649        data = new_data
650        return (directive, info, data)
651
652    def _process_data(self, results, directive, info, data):
653        new_data = []
654        for l in results[1]:
655            if l.startswith('%error'):
656                l = self._expand(l)
657                raise error.general('config error: %s' % (l[7:]))
658            elif l.startswith('%warning'):
659                l = self._expand(l)
660                log.stderr('warning: %s' % (l[9:]))
661                log.warning(l[9:])
662            if not directive:
663                l = self._expand(l)
664                ls = self.tags.split(l, 1)
665                log.trace('config: %s: _tag: %s %s' % (self.init_name, l, ls))
666                if len(ls) > 1:
667                    info = ls[0].lower()
668                    if info[-1] == ':':
669                        info = info[:-1]
670                    info_data = ls[1].strip()
671                else:
672                    info_data = ls[0].strip()
673                if info is not None:
674                    self._info_append(info, info_data)
675                else:
676                    log.warning("invalid format: '%s'" % (info_data[:-1]))
677            else:
678                log.trace('config: %s: _data: %s %s' % (self.init_name, l, new_data))
679                new_data.append(l)
680        return (directive, info, data + new_data)
681
682    def _process_block(self, results, directive, info, data):
683        raise error.internal('known block type: %s' % (results[0]))
684
685    def _directive_extend(self, dir, data):
686        pass
687
688    def _directive_filter(self, results, directive, info, data):
689        return directive, into, data
690
691    def _info_append(self, info, data):
692        pass
693
694    def load(self, name):
695
696        def common_end(left, right):
697            end = ''
698            while len(left) and len(right):
699                if left[-1] != right[-1]:
700                    return end
701                end = left[-1] + end
702                left = left[:-1]
703                right = right[:-1]
704            return end
705
706        if self.load_depth == 0:
707            self.in_error = False
708            self.lc = 0
709            self.name = name
710            self.conditionals = {}
711
712        self.load_depth += 1
713
714        save_name = self.name
715        save_lc = self.lc
716
717        self.name = name
718        self.lc = 0
719
720        #
721        # Locate the config file. Expand any macros then add the
722        # extension. Check if the file exists, therefore directly
723        # referenced. If not see if the file contains ':' or the path
724        # separator. If it does split the path else use the standard config dir
725        # path in the defaults.
726        #
727        exname = self.expand(name)
728
729        #
730        # Macro could add an extension.
731        #
732        if exname.endswith('.cfg'):
733            configname = exname
734        else:
735            configname = '%s.cfg' % (exname)
736            name = '%s.cfg' % (name)
737
738        if ':' in configname:
739            cfgname = path.basename(configname)
740        else:
741            cfgname = common_end(configname, name)
742
743        if not path.exists(configname):
744            if ':' in configname:
745                configdirs = path.dirname(configname).split(':')
746            else:
747                configdirs = self.define('_configdir').split(':')
748            for cp in configdirs:
749                configname = path.join(path.abspath(cp), cfgname)
750                if path.exists(configname):
751                    break
752                configname = None
753            if configname is None:
754                raise error.general('no config file found: %s' % (cfgname))
755
756        try:
757            log.trace('config: %s: _open: %s' % (self.init_name, path.host(configname)))
758            config = open(path.host(configname), 'r')
759        except IOError as err:
760            raise error.general('error opening config file: %s' % (path.host(configname)))
761        self.configpath += [configname]
762
763        self._includes += [configname]
764
765        try:
766            dir = None
767            info = None
768            data = []
769            while True:
770                r = self._parse(config, dir, info)
771                if r[0] == 'control':
772                    if r[1] == '%end':
773                        break
774                    log.warning("unexpected '%s'" % (r[1]))
775                elif r[0] == 'directive':
776                    if r[1] == '%include':
777                        self.load(r[2][0])
778                        continue
779                    dir, info, data = self._process_directive(r, dir, info, data)
780                elif r[0] == 'data':
781                    dir, info, data = self._process_data(r, dir, info, data)
782                else:
783                    self._error("%d: invalid parse state: '%s" % (self.lc, r[0]))
784            if dir is not None:
785                self._directive_extend(dir, data)
786        except:
787            config.close()
788            raise
789
790        config.close()
791
792        self.name = save_name
793        self.lc = save_lc
794
795        self.load_depth -= 1
796
797    def defined(self, name):
798        return self.macros.has_key(name)
799
800    def define(self, name):
801        if name in self.macros:
802            d = self.macros[name]
803        else:
804            n = self._label(name)
805            if n in self.macros:
806                d = self.macros[n]
807            else:
808                raise error.general('%d: macro "%s" not found' % (self.lc, name))
809        return self._expand(d)
810
811    def set_define(self, name, value):
812        self.macros[name] = value
813
814    def expand(self, line):
815        if type(line) == list:
816            el = []
817            for l in line:
818                el += [self._expand(l)]
819            return el
820        return self._expand(line)
821
822    def macro(self, name):
823        if name in self.macros:
824            return self.macros[name]
825        raise error.general('macro "%s" not found' % (name))
826
827    def directive(self, name):
828        pass
829
830    def abspath(self, rpath):
831        return path.abspath(self.define(rpath))
832
833    def includes(self):
834        return self._includes
835
836    def file_name(self):
837        return self.init_name
838
839def run():
840    import sys
841    try:
842        #
843        # Run where defaults.mc is located
844        #
845        opts = options.load(sys.argv, defaults = 'defaults.mc')
846        log.trace('config: count %d' % (len(opts.config_files())))
847        for config_file in opts.config_files():
848            s = file(config_file, opts)
849            print(s)
850            del s
851    except error.general as gerr:
852        print(gerr)
853        sys.exit(1)
854    except error.internal as ierr:
855        print(ierr)
856        sys.exit(1)
857    except KeyboardInterrupt:
858        log.notice('abort: user terminated')
859        sys.exit(1)
860    sys.exit(0)
861
862if __name__ == "__main__":
863    run()
Note: See TracBrowser for help on using the repository browser.