text: #!/usr/bin/python3
  """
  SPDX-License-Identifier: BSD-2
  """
  
  import os
  import pathlib
  import re
  import sys
  import textwrap
  
  
  def remove_common_guards(s):
  
      # Remove includes and guards
      s = re.sub("#ifndef.*", "", s)
      s = re.sub("#define .*_H\n", "", s)
      s = re.sub("#endif.*", "", s)
      s = re.sub("#error.*", "", s)
      s = re.sub('#ifdef __cplusplus\nextern "C" {', "", s, flags=re.MULTILINE)
      s = re.sub("#ifdef __cplusplus\n}", "", s, flags=re.MULTILINE)
      s = re.sub("#include.*", "", s)
  
      # Remove certain makros
      s = re.sub("#define TSS2_API_VERSION.*", "", s)
      s = re.sub("#define TSS2_ABI_VERSION.*", "", s)
      s = re.sub("#define TSS2_RC_LAYER\(level\).*", "", s)
      s = re.sub("(#define.*)TSS2_RC_LAYER\(0xff\)", "\g<1>0xff0000", s)
  
      # Remove comments
      s = re.sub("/\*.*?\*/", "", s, flags=re.MULTILINE)
  
      # Restructure #defines with ...
      s = re.sub("(#define [A-Za-z0-9_]+) +\(\(.*?\) \(.*?\)\)", "\g<1>...", s)
      s = re.sub("(#define [A-Za-z0-9_]+) +\(\(.*?\).*?\) ", "\g<1>...", s)
      s = re.sub(
          "(#define [A-Za-z0-9_]+) .*\n.*?.*\)\)", "\g<1>...", s, flags=re.MULTILINE
      )
      s = re.sub("(#define [A-Za-z0-9_]+) .*", "\g<1>...", s)
  
      # Restructure structs and untions with ...
      s = re.sub("\[.+?\]", "[...]", s)
  
      return s
  
  
  def remove_poll_stuff(s, poll_handle_type):
  
      r = r"#if defined\(__linux__\) \|\| defined\(__unix__\) \|\| defined\(__APPLE__\) \|\| defined \(__QNXNTO__\) \|\| defined \(__VXWORKS__\)(\n.*)+#endif\n#endif"
  
      s = re.sub(r, f"typedef struct pollfd {poll_handle_type};", s)
      return s
  
  
  def prepare_common(dirpath):
  
      s = pathlib.Path(dirpath, "tss2_common.h").read_text(encoding="utf-8")
  
      return remove_common_guards(s)
  
  
  def prepare_types(dirpath):
  
      s = pathlib.Path(dirpath, "tss2_tpm2_types.h").read_text(encoding="utf-8")
  
      # Remove false define (workaround)
      s = re.sub(
          "#define TPM2_MAX_TAGGED_POLICIES.*\n.*TPMS_TAGGED_POLICY\)\)",
          "",
          s,
          flags=re.MULTILINE,
      )
  
      return remove_common_guards(s)
  
  
  def prepare_tcti(dirpath):
  
      s = pathlib.Path(dirpath, "tss2_tcti.h").read_text(encoding="utf-8")
  
      s = re.sub("#ifndef TSS2_API_VERSION.*\n.*\n#endif", "", s, flags=re.MULTILINE)
  
      s = remove_poll_stuff(s, "TSS2_TCTI_POLL_HANDLE")
  
      s = re.sub(r"#define TSS2_TCTI_.*\n.*", "", s, flags=re.MULTILINE)
      s = re.sub(r"^\s*#define Tss2_Tcti_(?:.*\\\r?\n)*.*$", "", s, flags=re.MULTILINE)
  
      return remove_common_guards(s)
  
  
  def prepare_tcti_ldr(dirpath):
  
      s = pathlib.Path(dirpath, "tss2_tctildr.h").read_text(encoding="utf-8")
  
      return remove_common_guards(s)
  
  
  def prepare_sapi():
      return "typedef struct TSS2_SYS_CONTEXT TSS2_SYS_CONTEXT;"
  
  
  def prepare_esapi(dirpath):
  
      s = pathlib.Path(dirpath, "tss2_esys.h").read_text(encoding="utf-8")
      return remove_common_guards(s)
  
  
  def prepare_fapi(dirpath):
  
      s = pathlib.Path(dirpath, "tss2_fapi.h").read_text(encoding="utf-8")
  
      s = remove_poll_stuff(s, "FAPI_POLL_HANDLE")
  
      return remove_common_guards(s)
  
  
  def prepare_rcdecode(dirpath):
  
      s = pathlib.Path(dirpath, "tss2_rc.h").read_text(encoding="utf-8")
  
      return remove_common_guards(s)
  
  
  def prepare_mu(dirpath):
  
      s = pathlib.Path(dirpath, "tss2_mu.h").read_text(encoding="utf-8")
  
      s = remove_common_guards(s)
  
      # At least tpm2-tss 3.0.3 have duplicated BYTE (un)marshal functions which break cffi
      # So removing them is needed until 3.1.x has reached most distributions
      n = re.findall(
          "TSS2_RC\s+Tss2_MU_BYTE_Marshal\(.+?\);", s, re.DOTALL | re.MULTILINE
      )
      if len(n) > 1:
          s = re.sub(
              "TSS2_RC\s+Tss2_MU_BYTE_Marshal\(.+?\);", "", s, 1, re.DOTALL | re.MULTILINE
          )
  
      n = re.findall(
          "TSS2_RC\s+Tss2_MU_BYTE_Unmarshal\(.+?\);", s, re.DOTALL | re.MULTILINE
      )
      if len(n) > 1:
          s = re.sub(
              "TSS2_RC\s+Tss2_MU_BYTE_Unmarshal\(.+?\);",
              "",
              s,
              1,
              re.DOTALL | re.MULTILINE,
          )
  
      return s
  
  
  def prepare(indir, outfile):
      indir = os.path.join(indir, "tss2")
  
      common = prepare_common(indir)
  
      types = prepare_types(indir)
  
      tcti = prepare_tcti(indir)
  
      tcti_ldr = prepare_tcti_ldr(indir)
  
      sapi = prepare_sapi()
  
      esapi = prepare_esapi(indir)
  
      fapi = prepare_fapi(indir)
  
      rcdecode = prepare_rcdecode(indir)
  
      mu = prepare_mu(indir)
  
      # Write result
      with open(outfile, "w") as f:
          f.write(
              textwrap.dedent(
                  """
              /*
               * SPDX-License-Identifier: BSD-2
               * This file was automatically generated. Do not modify !
               */
              """
              )
          )
  
          f.write(common)
          f.write(types)
          f.write(tcti)
          f.write(tcti_ldr)
          f.write(sapi)
          f.write(esapi)
          f.write(fapi)
          f.write(rcdecode)
          f.write(mu)
  
  
  if __name__ == "__main__":
      if len(sys.argv) != 3:
          print("Usage: {0} <tss2-header-dir> <output-file>".format(sys.argv[0]))
          exit(1)
      prepare(sys.argv[1], sys.argv[2])
  