197 lines
4.9 KiB
Python
197 lines
4.9 KiB
Python
import logging
|
|
import sys
|
|
|
|
from c_common.scriptutil import (
|
|
CLIArgSpec as Arg,
|
|
add_verbosity_cli,
|
|
add_traceback_cli,
|
|
add_kind_filtering_cli,
|
|
add_files_cli,
|
|
add_failure_filtering_cli,
|
|
add_commands_cli,
|
|
process_args_by_key,
|
|
configure_logger,
|
|
get_prog,
|
|
main_for_filenames,
|
|
)
|
|
from . import (
|
|
errors as _errors,
|
|
get_preprocessor as _get_preprocessor,
|
|
)
|
|
|
|
|
|
FAIL = {
|
|
'err': _errors.ErrorDirectiveError,
|
|
'deps': _errors.MissingDependenciesError,
|
|
'os': _errors.OSMismatchError,
|
|
}
|
|
FAIL_DEFAULT = tuple(v for v in FAIL if v != 'os')
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
##################################
|
|
# CLI helpers
|
|
|
|
def add_common_cli(parser, *, get_preprocessor=_get_preprocessor):
|
|
parser.add_argument('--macros', action='append')
|
|
parser.add_argument('--incldirs', action='append')
|
|
parser.add_argument('--same', action='append')
|
|
process_fail_arg = add_failure_filtering_cli(parser, FAIL)
|
|
|
|
def process_args(args):
|
|
ns = vars(args)
|
|
|
|
process_fail_arg(args)
|
|
ignore_exc = ns.pop('ignore_exc')
|
|
# We later pass ignore_exc to _get_preprocessor().
|
|
|
|
args.get_file_preprocessor = get_preprocessor(
|
|
file_macros=ns.pop('macros'),
|
|
file_incldirs=ns.pop('incldirs'),
|
|
file_same=ns.pop('same'),
|
|
ignore_exc=ignore_exc,
|
|
log_err=print,
|
|
)
|
|
return process_args
|
|
|
|
|
|
def _iter_preprocessed(filename, *,
|
|
get_preprocessor,
|
|
match_kind=None,
|
|
pure=False,
|
|
):
|
|
preprocess = get_preprocessor(filename)
|
|
for line in preprocess(tool=not pure) or ():
|
|
if match_kind is not None and not match_kind(line.kind):
|
|
continue
|
|
yield line
|
|
|
|
|
|
#######################################
|
|
# the commands
|
|
|
|
def _cli_preprocess(parser, excluded=None, **prepr_kwargs):
|
|
parser.add_argument('--pure', action='store_true')
|
|
parser.add_argument('--no-pure', dest='pure', action='store_const', const=False)
|
|
process_kinds = add_kind_filtering_cli(parser)
|
|
process_common = add_common_cli(parser, **prepr_kwargs)
|
|
parser.add_argument('--raw', action='store_true')
|
|
process_files = add_files_cli(parser, excluded=excluded)
|
|
|
|
return [
|
|
process_kinds,
|
|
process_common,
|
|
process_files,
|
|
]
|
|
|
|
|
|
def cmd_preprocess(filenames, *,
|
|
raw=False,
|
|
iter_filenames=None,
|
|
**kwargs
|
|
):
|
|
if 'get_file_preprocessor' not in kwargs:
|
|
kwargs['get_file_preprocessor'] = _get_preprocessor()
|
|
if raw:
|
|
def show_file(filename, lines):
|
|
for line in lines:
|
|
print(line)
|
|
#print(line.raw)
|
|
else:
|
|
def show_file(filename, lines):
|
|
for line in lines:
|
|
linefile = ''
|
|
if line.filename != filename:
|
|
linefile = f' ({line.filename})'
|
|
text = line.data
|
|
if line.kind == 'comment':
|
|
text = '/* ' + line.data.splitlines()[0]
|
|
text += ' */' if '\n' in line.data else r'\n... */'
|
|
print(f' {line.lno:>4} {line.kind:10} | {text}')
|
|
|
|
filenames = main_for_filenames(filenames, iter_filenames)
|
|
for filename in filenames:
|
|
lines = _iter_preprocessed(filename, **kwargs)
|
|
show_file(filename, lines)
|
|
|
|
|
|
def _cli_data(parser):
|
|
...
|
|
|
|
return None
|
|
|
|
|
|
def cmd_data(filenames,
|
|
**kwargs
|
|
):
|
|
# XXX
|
|
raise NotImplementedError
|
|
|
|
|
|
COMMANDS = {
|
|
'preprocess': (
|
|
'preprocess the given C source & header files',
|
|
[_cli_preprocess],
|
|
cmd_preprocess,
|
|
),
|
|
'data': (
|
|
'check/manage local data (e.g. excludes, macros)',
|
|
[_cli_data],
|
|
cmd_data,
|
|
),
|
|
}
|
|
|
|
|
|
#######################################
|
|
# the script
|
|
|
|
def parse_args(argv=sys.argv[1:], prog=sys.argv[0], *,
|
|
subset='preprocess',
|
|
excluded=None,
|
|
**prepr_kwargs
|
|
):
|
|
import argparse
|
|
parser = argparse.ArgumentParser(
|
|
prog=prog or get_prog(),
|
|
)
|
|
|
|
processors = add_commands_cli(
|
|
parser,
|
|
commands={k: v[1] for k, v in COMMANDS.items()},
|
|
commonspecs=[
|
|
add_verbosity_cli,
|
|
add_traceback_cli,
|
|
],
|
|
subset=subset,
|
|
)
|
|
|
|
args = parser.parse_args(argv)
|
|
ns = vars(args)
|
|
|
|
cmd = ns.pop('cmd')
|
|
|
|
verbosity, traceback_cm = process_args_by_key(
|
|
args,
|
|
processors[cmd],
|
|
['verbosity', 'traceback_cm'],
|
|
)
|
|
|
|
return cmd, ns, verbosity, traceback_cm
|
|
|
|
|
|
def main(cmd, cmd_kwargs):
|
|
try:
|
|
run_cmd = COMMANDS[cmd][0]
|
|
except KeyError:
|
|
raise ValueError(f'unsupported cmd {cmd!r}')
|
|
run_cmd(**cmd_kwargs)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
cmd, cmd_kwargs, verbosity, traceback_cm = parse_args()
|
|
configure_logger(verbosity)
|
|
with traceback_cm:
|
|
main(cmd, cmd_kwargs)
|