source: rtems-source-builder/tb/config.py @ bf13d27

4.104.114.95
Last change on this file since bf13d27 was bf13d27, checked in by Chris Johns <chrisj@…>, on Oct 29, 2012 at 11:37:12 PM

Initial import.

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