parent
ff8da9d246
commit
c07e4a8c01
333 changed files with 0 additions and 95037 deletions
|
@ -1,194 +0,0 @@
|
|||
#! /usr/bin/env python3
|
||||
"""Minimal macro processor. Used for generating VC++ makefiles.
|
||||
|
||||
The available template commands are:
|
||||
|
||||
Expand a template section for each file in a list of file patterns::
|
||||
###MAKTEMPLATE:FOREACH my/path*/*.cxx,other*.cxx
|
||||
...
|
||||
###MAKTEMPLATE:ENDFOREACH
|
||||
|
||||
In the template section, you can use `###BASENAME###` to get the base name
|
||||
of the file being processed (e.g. "base" for "../base.cxx"), and you can
|
||||
use `###FILENAME###` to get the full filename.
|
||||
|
||||
|
||||
Copyright (c) 2000-2022, Bart Samwel and Jeroen T. Vermeulen.
|
||||
"""
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
from argparse import (
|
||||
ArgumentError,
|
||||
ArgumentParser,
|
||||
RawDescriptionHelpFormatter,
|
||||
)
|
||||
from contextlib import contextmanager
|
||||
from glob import glob
|
||||
import os
|
||||
from sys import (
|
||||
argv,
|
||||
stdin,
|
||||
stderr,
|
||||
stdout,
|
||||
)
|
||||
import sys
|
||||
from textwrap import dedent
|
||||
|
||||
|
||||
def expand_foreach_file(path, block, outfile):
|
||||
"""Expand a "foreach" block for a single file path.
|
||||
|
||||
Write the results to outfile.
|
||||
"""
|
||||
basepath, _ = os.path.splitext(os.path.basename(path))
|
||||
for line in block:
|
||||
line = line.replace("###FILENAME###", path)
|
||||
line = line.replace("###BASENAME###", basepath)
|
||||
outfile.write(line)
|
||||
|
||||
|
||||
def match_globs(globs):
|
||||
"""List all files matching any item in globs.
|
||||
|
||||
Eliminates duplicates.
|
||||
"""
|
||||
return sorted({
|
||||
path
|
||||
for pattern in globs
|
||||
for path in glob(pattern)
|
||||
})
|
||||
|
||||
|
||||
def expand_foreach(globs, block, outfile):
|
||||
"""Expand a foreach block for each file matching one of globs.
|
||||
|
||||
Write the results to outfile.
|
||||
"""
|
||||
# We'll be iterating over block a variable number of times. Turn it
|
||||
# from a generic iterable into an immutable array.
|
||||
block = tuple(block)
|
||||
for path in match_globs(globs):
|
||||
expand_foreach_file(path, block, outfile)
|
||||
|
||||
|
||||
# Header to be prefixed to the generated file.
|
||||
OUTPUT_HEADER = dedent("""\
|
||||
# AUTOMATICALLY GENERATED FILE -- DO NOT EDIT.
|
||||
#
|
||||
# This file is generated automatically by libpqxx's {script} script, and
|
||||
# will be rewritten from time to time.
|
||||
#
|
||||
# If you modify this file, chances are your modifications will be lost.
|
||||
#
|
||||
# The {script} script should be available in the tools directory of the
|
||||
# libpqxx source archive.
|
||||
""")
|
||||
|
||||
|
||||
foreach_marker = r"###MAKTEMPLATE:FOREACH "
|
||||
end_foreach_marker = r"###MAKTEMPLATE:ENDFOREACH"
|
||||
|
||||
|
||||
def parse_foreach(line):
|
||||
"""Parse FOREACH directive, if line contains one.
|
||||
|
||||
:param line: One line of template input.
|
||||
:return: A list of FOREACH globs, or None if this was not a FOREACH line.
|
||||
"""
|
||||
line = line.strip()
|
||||
if line.startswith(foreach_marker):
|
||||
return line[len(foreach_marker):].split(',')
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def read_foreach_block(infile):
|
||||
"""Read a FOREACH block from infile (not including the FOREACH directive).
|
||||
|
||||
Assumes that the FOREACH directive was in the preceding line. Consumes
|
||||
the line with the ENDFOREACH directive, but does not yield it.
|
||||
|
||||
:return: Iterable of lines.
|
||||
"""
|
||||
for line in infile:
|
||||
if line.strip().startswith(end_foreach_marker):
|
||||
return
|
||||
yield line
|
||||
|
||||
|
||||
def expand_template(infile, outfile):
|
||||
"""Expand the template in infile, and write the results to outfile."""
|
||||
for line in infile:
|
||||
globs = parse_foreach(line)
|
||||
if globs is None:
|
||||
# Not a FOREACH line. Copy to output.
|
||||
outfile.write(line)
|
||||
else:
|
||||
block = read_foreach_block(infile)
|
||||
expand_foreach(globs, block, outfile)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def open_stream(path=None, default=None, mode='r'):
|
||||
"""Open file at given path, or yield default. Close as appropriate.
|
||||
|
||||
The default should be a stream, not a path; closing the context will not
|
||||
close it.
|
||||
"""
|
||||
if path is None:
|
||||
yield default
|
||||
else:
|
||||
with open(path, mode) as stream:
|
||||
yield stream
|
||||
|
||||
|
||||
def parse_args():
|
||||
"""Parse command-line arguments.
|
||||
|
||||
:return: Tuple of: input path (or None for stdin), output path (or None
|
||||
for stdout).
|
||||
"""
|
||||
parser = ArgumentParser(
|
||||
description=__doc__, formatter_class=RawDescriptionHelpFormatter)
|
||||
|
||||
parser.add_argument(
|
||||
'template', nargs='?',
|
||||
help="Input template. Defaults to standard input.")
|
||||
parser.add_argument(
|
||||
'output', nargs='?',
|
||||
help="Output file. Defaults to standard output.")
|
||||
|
||||
args = parser.parse_args()
|
||||
return args.template, args.output
|
||||
|
||||
|
||||
def write_header(stream, template_path=None):
|
||||
"""Write header to stream."""
|
||||
hr = ('# ' + '#' * 78) + "\n"
|
||||
script = os.path.basename(argv[0])
|
||||
|
||||
outstream.write(hr)
|
||||
outstream.write(OUTPUT_HEADER.format(script=script))
|
||||
if template_path is not None:
|
||||
outstream.write("#\n")
|
||||
outstream.write("# Generated from template '%s'.\n" % template_path)
|
||||
outstream.write(hr)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
template_path, output_path = parse_args()
|
||||
except ArgumentError as error:
|
||||
stderr.write('%s\n' % error)
|
||||
sys.exit(2)
|
||||
|
||||
input_stream = open_stream(template_path, stdin, 'r')
|
||||
output_stream = open_stream(output_path, stdout, 'w')
|
||||
with input_stream as instream, output_stream as outstream:
|
||||
write_header(outstream, template_path)
|
||||
expand_template(instream, outstream)
|
Loading…
Add table
Add a link
Reference in a new issue