"""AUX CPP
Auxilary file for the cpp converter.
"""
import os
from excentury.command import error, trace, exec_cmd, date
from excentury.lang import format_input, format_return, gen_cmd
from excentury.lang import write_file
from datetime import datetime
TEMPLATE = """// File generated on {date} by xcpp.
#define XC_CPP
{preamble}{funcpre}void xc_help() {{
fprintf(stderr,
{help});
}}
void xc_input() {{
xc_help();
excentury::TextInterface<excentury::dump_mode> XC_DI_(stdout);
{param} XC_DI_.close();
}}
int main(int argc, char** argv) {{
/*{doc}*/
excentury::check_inputs(argc);
excentury::print_help(argv, xc_help);
excentury::print_inputs(argv, xc_input);
excentury::S{load}Interface<excentury::load_mode> XC_LI_(argv[1]);
{input} XC_LI_.close();
{body}
excentury::{dump}Interface<excentury::dump_mode> XC_DI_({out});
{output}
XC_DI_.close();
}}
{funcepi}{epilog}
"""
def _format_help(func, fname):
"""Generate the help string. """
msg = ' "program: %s-%s\\n"\n' % (fname, func.name)
msg += ' "\\ndescription:\\n"\n " '
msg += '\\n"\n "'.join(func.doc.split('\n'))
if func.param:
msg += '\\n"\n "\\nparameters:\\n"\n'
tmp = ' " {0}: {1}\\n"\n'
for par in func.param:
msg += tmp.format(par['name'], par['desc'])
msg += ' "\\n"'
else:
msg += '\\n"\n "\\n"'
return msg
def _format_input(param):
"""Return a string with all the inputs property formatted. """
inputs = ''
for par in param:
tmp = ' {type} {var}{ctor}; XC_DI_.dump({var}, "{var}"'
if 'sample' in par:
tmp += ', %s);\n' % par['sample']
else:
tmp += ');\n'
inputs += tmp.format(type=par['type'], var=par['name'][1:-1],
ctor=par['ctor'])
return inputs
def _write_file(contents, func, cfg):
"""Helper function for process_function. """
root = cfg['xcpp']['root']
cppdir = cfg['cpp']['dir']
if cppdir[0] == '/' or cppdir == '.':
base = cppdir
else:
base = '%s/%s' % (root, cppdir)
filename = cfg['xcpp']['filename']
in_fname = '%s/%s-%s.cpp' % (base, filename, func.name)
msg = '[%d] inspecting %s-%s.cpp ... '
trace(msg % (func.num, filename, func.name))
write_file(in_fname, contents)
return in_fname
def _get_exec_name(func, cfg):
"""Helper function to process_function. """
filename = cfg['xcpp']['filename']
root = cfg['xcpp']['root']
bindir = cfg['cpp']['bin']
if bindir[0] == '/' or bindir == '.':
base = bindir
else:
base = '%s/%s' % (root, bindir)
dbg = cfg['cpp']['debug'] if cfg['cpp']['debug'] != '0' else ''
ext = cfg['cpp']['ext']
if ext == '':
out_fname = '%s/%s-%s%s' % (base, filename, func.name, dbg)
else:
out_fname = '%s/%s-%s.%s%s' % (base, filename, func.name, ext, dbg)
return out_fname
[docs]def process_function(xcf, cfg, func):
"""Given a Function object from .xcpp it will create the contents
of a valid cpp file that can be compiled for a valid executable.
"""
in_fname = cfg['xcpp']['filename']
epilog = func.epilog
if epilog != '':
epilog += '\n'
contents = TEMPLATE.format(date=date(), pre_xc=xcf.pre_xc,
preamble=xcf.preamble,
help=_format_help(func, in_fname),
param=_format_input(func.param),
doc=func.doc, body=func.body,
load=cfg['cpp']['load'].capitalize(),
dump=cfg['cpp']['dump'].capitalize(),
input=format_input(func.param),
output=format_return(func.ret),
out=func.out, funcpre=func.preamble,
funcepi=epilog, epilog=xcf.epilog)
in_fname = _write_file(contents, func, cfg)
out_fname = _get_exec_name(func, cfg)
force = cfg['cpp']['force']
make_new = True
if isinstance(force, list) and (len(force) == 0 or func.num in force):
pass
elif force in ['True', 'true']:
pass
elif os.path.exists(out_fname):
date_in = datetime.fromtimestamp(os.path.getmtime(in_fname))
date_out = datetime.fromtimestamp(os.path.getmtime(out_fname))
if date_in < date_out:
make_new = False
trace(' - skipping compilation\n')
if make_new:
cmd = gen_cmd(cfg, 'cpp', int(cfg['cpp']['debug']))
cmd = '%s%s -o %s' % (cmd, in_fname, out_fname)
trace(' - compiling %s ... ' % in_fname)
_, err, _ = exec_cmd(cmd)
if err != '':
msg = "\nERROR: The command\n%s\n\nreturned the following " \
"error:\n%s" % (str(cmd), str(err))
error(msg)
trace('done\n')