File: splitconfig

package info (click to toggle)
libpqxx 4.0.1%2Bdfsg3-8
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 16,012 kB
  • ctags: 9,469
  • sloc: sh: 11,289; cpp: 10,801; xml: 1,256; makefile: 287; ansic: 195; python: 159
file content (154 lines) | stat: -rwxr-xr-x 4,917 bytes parent folder | download | duplicates (2)
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#! /usr/bin/python

"""Extract configuration items into various configuration headers.

This uses the configitems file, a database consisting of text lines with the
following single-tab-separated fields:
 - Name of the configuration item, e.g. PQXX_HAVE_PTRDIFF_T.
 - Publication marker: public or internal.
 - A single environmental factor determining the item, e.g. libpq or compiler.
"""

from __future__ import (
    absolute_import,
    print_function,
    unicode_literals,
    )

__metaclass__ = type

import os.path
import re
import sys

usage = """\
Usage: splitconfig [srcdir]

where [srcdir] is the main libpqxx source directory containing the configitems
file, the include directory etc.  This defaults to the current directory.
"""

def help_and_exit(error_string=None):
    if error_string != None:
        sys.stderr.write(error_string + '\n')
    print(usage)
    if ok:
        sys.exit(0)
    else:
        sys.exit(1)


def read_configitems(filename):
    """Read the configuration-items database.

    :param filename: Path to the configitems file.
    :return: Sequence of text lines from configitems file.
    """
    text = open(filename, 'rb').read().decode('ascii')
    return [line.split() for line in text.splitlines()]


def map_configitems(items):
    """Map each config item to publication/factor.

    :param items: Sequence of config items: (name, publication, factor).
    :return: Dict mapping each item name to a tuple (publication, factor).
    """
    return dict(
        (item, (publication, factor))
        for item, publication, factor in items)


def read_header(filename):
    """Read the original config.h generated by autoconf.

    :param filename: Path to the config.h file.
    :return: Sequence of text lines from config.h.
    """
    return open(filename, 'rb').read().decode('ascii').splitlines()


def extract_macro_name(config_line):
    """Extract a cpp macro name from a configuration line.

    :param config_line: Text line from config.h which may define a macro.
    :return: Name of macro defined in `config_line` if it is a `#define`
        statement, or None.
    """
    config_line = config_line.strip()
    match = re.match('\s*#\s*define\s+([^\s]+)', config_line)
    if match is None:
        return None
    else:
        return match.group(1)


def extract_section(header_lines, items, publication, factor):
    """Extract config items for given publication/factor from header lines.

    :param header_lines: Sequence of header lines from config.h.
    :param items: Dict mapping macro names to (publication, factor).
    :param publication: Extract only macros for this publication tag.
    :param factor: Extract only macros for this environmental factor.
    :return: Sequence of `#define` lines from `header_lines` insofar they
        fall within the requested section.
    """
    return sorted(
        line.strip()
        for line in header_lines
            if items.get(extract_macro_name(line)) == (publication, factor))


def generate_config(header_lines, items, publication, factor):
    """Generate config file for a given section.  Skip empty ones.

    :param header_lines: Sequence of header lines from config.h.
    :param items: Dict mapping macro names to (publication, factor).
    :param publication: Extract only macros for this publication tag.
    :param factor: Extract only macros for this environmental factor.
    """
    config_file = "include/pqxx/config-%s-%s.h" % (publication, factor)
    section = extract_section(header_lines, items, publication, factor)
    if len(section) == 0:
        print("Generating %s: no items--skipping." % config_file)
        return
    with open(config_file, 'wb') as header:
        header.write(
            "/* Automatically generated from config.h: %s/%s config. */\n"
            % (publication, factor))
        header.write('\n'.join(section))
        header.write('\n')
    print("Generating %s: %d item(s)." % (config_file, len(section)))


def check_args(argv):
    if len(argv) > 2:
        help_and_exit("Too many arguments.")

    if len(argv) == 2:
        if argv[1] in ('-h', '--help'):
            help_and_exit()
        if not os.path.isdir(argv[1]):
            help_and_exit("%s is not a directory." % srcdir)


def get_base_dir(argv):
    if len(argv) > 1:
        return argv[1]
    else:
        return "."


if __name__ == '__main__':
    check_args(sys.argv)
    srcdir = get_base_dir(sys.argv)
    items = read_configitems(os.path.join(srcdir, "configitems"))
    config = map_configitems(items)
    publications = sorted(set(item[1] for item in items))
    factors = sorted(set(item[2] for item in items))
    original_header = read_header("include/pqxx/config.h")
    items_map = map_configitems(items)

    for publication in publications:
        for factor in factors:
            generate_config(original_header, items_map, publication, factor)