#!/usr/bin/env python
from __future__ import print_function, division, absolute_import #, unicode_literals

import os
import re
import sys

from optparse import OptionParser
from time import gmtime,strftime

# ---------------------------------------------------------------------------- #

#
# Main program
#

# Initial setup
my_name     = "make-cppopts-dumper"
my_output   = "shared/common/src/14_hidewrite/m_cppopts_dumper.F90"

# Check if we are in the top of the ABINIT source tree
if ( not os.path.exists("configure.ac") or
     not os.path.exists("src/98_main/abinit.F90") ):
  print("%s: You must be in the top of an ABINIT source tree." % my_name)
  print("%s: Aborting now." % my_name)
  sys.exit(1)

# What time is it?
now = strftime("%Y/%m/%d %H:%M:%S +0000",gmtime())

# Init template
cppopts_dumper_module = """\
!{\src2tex{textfont=tt}}
!!****m* ABINIT/m_cppopts_dumper
!! NAME
!!  m_cppopts_dumper
!!
!! FUNCTION
!!  Displays preprocessing options activated at compile-time.
!!
!! COPYRIGHT
!!  Copyright (C) 2010-2020 ABINIT group (Yann Pouillon)
!!  This file is distributed under the terms of the
!!  GNU General Public License, see ~abinit/COPYING
!!  or http://www.gnu.org/copyleft/gpl.txt.
!!
!! NOTES
!!  This file was generated by %s,
!!  on %s.
!!  Any modification will be lost.
!!
!! PARENTS
!!
!! CHILDREN
!!
!! SOURCE

#if defined HAVE_CONFIG_H
#include "config.h"
#endif

module m_cppopts_dumper

  implicit none

  public :: dump_cpp_options

contains
!!***

!!****f* ABINIT/m_cppopts_dumper/dump_cpp_options
!! NAME
!!  dump_cpp_options
!!
!! FUNCTION
!!  Reports a printout of the CPP options used at compile-time,
!!  useful for error messages and debugging.
!!
!! INPUTS
!!  my_unit= Fortran unit number (optional, default is std_out)
!!
!! OUTPUT
!!  Only printing.
!!
!! PARENTS
!!
!! CHILDREN
!!
!! SOURCE

subroutine dump_cpp_options(my_unit)

  use defs_basis

  implicit none

!Arguments -------------------------------------
  integer,intent(in) :: my_unit

!Local variables -------------------------------
  character(len=26) :: tmp
  character(len=80) :: msg
  integer :: msg_index

! **********************************************************************

  write(my_unit,"(a,1x,a)") ch10,repeat("+",78)
  write(my_unit,"(1x,a,a)") "CPP options activated during the build:",ch10

  msg_index = 0
  msg = ""

@CPP_OPTIONS@
  if ( mod(msg_index,3) /= 0 ) write(my_unit,'(a)') msg

  write(my_unit,"(1x,a,a)") repeat("+",78),ch10

end subroutine dump_cpp_options

end module m_cppopts_dumper
!!***
""" % (my_name,now)

# Naming convention checker
def check_name(cpp_option,cpp_blocks):
  opt = cpp_option.split("_")
  ret = True
  for i in range(len(opt)):
    ret = (opt[i] in cpp_blocks[i])
    if ( not ret ):
      break
  return ret

# Parse command-line arguments
my_help = "Usage: %prog [-v|--verbose]"""
parser = OptionParser(usage=my_help, version="%prog for Abinit 7")
parser.add_option("-v", "--verbose", action="store_true",
  dest="verbose", default=False,
  help="Report developer options")
(opts, args) = parser.parse_args()
chk_verbose = opts.verbose

# Init script
my_name = os.path.basename(sys.argv[0])

# Init regular expressions
re_m4file  = re.compile("\.m4$")
re_acdef  = re.compile("AC_DEFINE\\(")

# Init CPP options
cpp_ignored = [
  "HAVE_CONFIG_H"]

# Extract CPP options from the build system
cpp_buildsys = list()
for root,dirs,files in os.walk("config/m4"):
  for src in files:
    if ( re_m4file.search(src) ):
      for line in open(os.path.join(root,src), "rt").readlines():
        if ( re_acdef.search(line) ):
          tmp_def = re.sub(".*AC_DEFINE\\([\\[]?([^\\],]*).*","\\1",line).strip()
          if ( not tmp_def in cpp_buildsys ):
            cpp_buildsys.append(tmp_def)
for line in open("configure.ac","rt").readlines():
  if ( re_acdef.search(line) ):
    tmp_def = re.sub(".*AC_DEFINE\\([\\[]?([^\\],]*).*","\\1",line).strip()
    if ( not tmp_def in cpp_buildsys ):
      cpp_buildsys.append(tmp_def)
cpp_buildsys.sort()

# Process CPP option information
cppopts_dumper_src = ""
for opt in cpp_buildsys:
  opt_shown = re.sub("BUG","B*G",opt)
  if ( len(opt_shown) > 25 ):
    opt_shown = opt_shown[0:22] + "..."
  if ( opt != "" ):
    cppopts_dumper_src += """\
#if defined %s
  write(tmp,"(1x,a25)") "%s"
  msg = trim(msg)//trim(tmp)
  msg_index = msg_index + 1
  if ( mod(msg_index,3) == 0 ) then
    msg = trim(msg)//ch10
    write(my_unit,'(a)') msg
    msg = ""
  end if
#endif
""" % (opt,opt_shown)

cppopts_dumper_module = re.sub("@CPP_OPTIONS@",cppopts_dumper_src, \
  cppopts_dumper_module)

open(my_output,"wt").write(cppopts_dumper_module)
