summaryrefslogtreecommitdiffhomepage
path: root/digital/ucoolib/build/tools/config-gen
blob: 3feffbe83e4391be3654eec97ed450ae5917b01e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/python
"""Read build configuration and generate header files."""
import optparse
import ConfigParser
import sys
import re
import os

def read_config(modules_configs, project_config):
    """Read configuration definitions and default values from module
    configuration files, then merge project configuration."""
    parser = ConfigParser.SafeConfigParser()
    # Read definitions and default values.
    for mc in modules_configs:
        try:
            mcf = open(mc)
        except IOError:
            pass
        else:
            with mcf:
                parser.readfp(mcf)
    # Save the list of existing items for later check.
    def config_items(parser):
        return set('%s:%s' % (section, item)
                for section in parser.sections()
                for item in parser.options(section))
    modules_items = config_items(parser)
    # Now read project configuration.
    if project_config is not None:
        try:
            pcf = open(project_config)
        except IOError:
            pass
        else:
            with pcf:
                parser.readfp(pcf)
        # Check for unknown items.
        project_items = config_items(parser)
        unknown_items = project_items - modules_items
        if unknown_items:
            raise RuntimeError("unknown configuration item: "
                    + " ".join(unknown_items))
        # Check for items with no default value.
        for section in parser.sections():
            for key, value in parser.items(section):
                if value == '':
                    raise RuntimeError("no value given for %s:%s"
                            % (section, key))
    # OK, convert to more natural structure.
    return dict((section, parser.items(section))
        for section in parser.sections())

def write_header(filename, section, section_dict):
    """Write (update) a section to a C header file."""
    # Prepare new content.
    items = [ ]
    section = section.replace('/', '_').upper()
    for key, value in section_dict:
        items.append('#define UCOO_CONFIG_%s_%s (%s)'
                % (section, key.upper(), value))
    guard = re.sub(r'\W', '_', filename)
    content = '\n'.join([
        '#ifndef %s' % guard,
        '#define %s' % guard,
        '// Generated from configuration.',
        ] + items + [
        '#endif',
        '' ])
    # Check old content.
    old_content = ''
    try:
        hf = open(filename)
    except IOError:
        pass
    else:
        with hf:
            old_content = hf.read()
    if old_content == content:
        return
    # Create output directory if needed.
    dirname = os.path.dirname(filename)
    if not os.path.exists(dirname):
        os.makedirs(dirname)
    # Write new content.
    with open(filename, 'w') as hf:
        hf.write(content)

def write_headers(filename_pattern, config):
    """Write (update) all sections to C header files."""
    for section, section_dict in config.iteritems():
        filename = filename_pattern.replace('%', section)
        write_header(filename, section, section_dict)

if __name__ == '__main__':
    parser = optparse.OptionParser(
            usage='%prog [options] modules configuration files...')
    parser.add_option('-p', '--project-config', metavar='FILE',
            help="project configuration file")
    parser.add_option('-H', '--c-header-template', metavar='TEMPLATE',
            help="name template for C header files"
            + " (use % as section placeholder)")
    options, modules_configs = parser.parse_args()

    try:
        config = read_config(modules_configs, options.project_config)
        if options.c_header_template:
            write_headers(options.c_header_template, config)
    except RuntimeError, e:
        print >> sys.stderr, e
        sys.exit(1)
    except EnvironmentError, e:
        print >> sys.stderr, e
        sys.exit(1)