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)
|