# Copyright (C) 2009-2018 Anders Logg and Garth N. Wells
#
# This file is part of FFCx. (https://www.fenicsproject.org)
#
# SPDX-License-Identifier: LGPL-3.0-or-later
"""Compiler stage 5: Code formatting.
This module implements the formatting of UFC code from a given
dictionary of generated C++ code for the body of each UFC function.
It relies on templates for UFC code available as part of the module
ufcx_utils.
"""
import logging
import os
import pprint
import textwrap
from ffcx import __version__ as FFCX_VERSION
from ffcx.codegeneration import __version__ as UFC_VERSION
logger = logging.getLogger("ffcx")
FORMAT_TEMPLATE = {
"ufc comment":
"""\
// This code conforms with the UFC specification version {ufcx_version}
// and was automatically generated by FFCx version {ffcx_version}.
""",
"dolfinx comment":
"""\
// This code conforms with the UFC specification version {ufcx_version}
// and was automatically generated by FFCx version {ffcx_version}.
//
""",
"header_h":
"""
#pragma once
""",
"header_c":
"""
""",
}
c_extern_pre = """
#ifdef __cplusplus
extern "C" {
#endif
"""
c_extern_post = """
#ifdef __cplusplus
}
#endif
"""
[docs]def write_code(code_h, code_c, prefix, output_dir):
_write_file(code_h, prefix, ".h", output_dir)
_write_file(code_c, prefix, ".c", output_dir)
def _write_file(output, prefix, postfix, output_dir):
"""Write generated code to file."""
filename = os.path.join(output_dir, prefix + postfix)
with open(filename, "w") as hfile:
hfile.write(output)
def _generate_comment(parameters):
"""Generate code for comment on top of file."""
# Generate top level comment
comment = FORMAT_TEMPLATE["ufc comment"].format(ffcx_version=FFCX_VERSION, ufcx_version=UFC_VERSION)
# Add parameter information
comment += "//\n"
comment += "// This code was generated with the following parameters:\n"
comment += "//\n"
comment += textwrap.indent(pprint.pformat(parameters), "// ")
comment += "\n"
return comment
def _generate_includes(parameters: dict):
default_h_includes = [
"#include <ufcx.h>",
]
default_c_includes = [
"#include <math.h>", # This should really be set by the backend
"#include <stdalign.h>", # This should really be set by the backend
"#include <stdlib.h>", # This should really be set by the backend
"#include <string.h>", # This should really be set by the backend
"#include <ufcx.h>"
]
if "_Complex" in parameters["scalar_type"]:
default_c_includes += ["#include <complex.h>"]
s_h = set(default_h_includes)
s_c = set(default_c_includes)
includes_h = "\n".join(sorted(s_h)) + "\n" if s_h else ""
includes_c = "\n".join(sorted(s_c)) + "\n" if s_c else ""
return includes_h, includes_c