# in projects where [ $mb_use_custom_cfgdefs = yes ],
# cfgdefs.sh is invoked from within ./configure via
# . $mb_project_dir/project/cfgdefs.sh

# a successful return from cfgdefs.sh will be followed
# by a second invocation of the config_copy() function,
# reflecting any changes to common config variables
# made by cfgdefs.sh.

# finally, cfgdefs.sh may update the contents of the
# config-time generated cfgdefs.mk.


# cfgdefs helper functions
. "$mb_project_dir/project/config/cfghost.sh"


# sofort's config test framework
. "$mb_project_dir/sofort/cfgtest.sh"


for arg ; do
	case "$arg" in
		*)
			error_msg ${arg#}: "unsupported config argument."
			exit 2
	esac
done


cfgdefs_set_cfghost_flavors()
{
	cfghost_set_target_cfghost
	cfghost_set_native_cfghost
}


cfgdefs_detect_python_version()
{
	mb_internal_verinfo=$(mktemp)

	if [ -z "$mb_internal_verinfo" ]; then
		exit 2
	fi

	"$mb_native_cc" -E -dM "$mb_source_dir/Include/patchlevel.h" \
		> "$mb_internal_verinfo"

	python_major=$(grep '#define PY_MAJOR_VERSION ' "$mb_internal_verinfo" | cut -d' ' -f3)
	python_minor=$(grep '#define PY_MINOR_VERSION ' "$mb_internal_verinfo" | cut -d' ' -f3)
	python_micro=$(grep '#define PY_MICRO_VERSION ' "$mb_internal_verinfo" | cut -d' ' -f3)

	if [ -z "$python_major" ] || [ -z "$python_minor" ] || [ -z "$python_micro" ]; then
		error_msg "Could not properly parse Python's patchlevel.h"
		exit 2
	fi

	python_ver="$python_major.$python_minor"

	[ -z "$mb_package"  ] && mb_package='python'"$python_ver"
	[ -z "$mb_nickname" ] && mb_nickname="$mb_package"
	[ -z "$mb_pkgname"  ] && mb_pkgname="$mb_package"
	[ -z "$mb_pkgdesc"  ] && mb_pkgdesc="$mb_package"
}


cfgdefs_output_custom_defs()
{
	sed \
			-e 's/@python_ver@/'"$python_ver"'/g'       \
			-e 's/@python_major@/'"$python_major"'/g'   \
			-e 's/@python_minor@/'"$python_minor"'/g'   \
			-e 's/@python_micro@/'"$python_micro"'/g'   \
		"$mb_project_dir/project/config/cfgdefs.in"         \
			>> "$mb_pwd/cfgdefs.mk"
}


cfgdefs_perform_common_tests()
{
	# headers
	cfgtest_header_absence  'stropts.h'
	cfgtest_header_presence 'stdatomic.h'
	cfgtest_header_presence 'endian.h'
	cfgtest_header_presence 'net/if.h'
	cfgtest_header_presence 'sched.h'
	cfgtest_header_presence 'sys/ioctl.h'
	cfgtest_header_presence 'sys/sendfile.h'
	cfgtest_header_presence 'sys/syscall.h'
	cfgtest_header_presence 'sys/sysmacros.h'
	cfgtest_header_presence 'sys/uio.h'
	cfgtest_header_presence 'sys/xattr.h'

	# interfaces
	mb_cfgtest_headers='sys/epoll.h'
	cfgtest_interface_presence 'epoll_create1'

	mb_cfgtest_headers='sched.h'
	cfgtest_interface_presence 'sched_get_priority_max'
	cfgtest_interface_presence 'sched_rr_get_interval'
	cfgtest_interface_presence 'sched_setaffinity'
	cfgtest_interface_presence 'sched_setparam'
	cfgtest_interface_presence 'sched_setscheduler'

	mb_cfgtest_headers='sys/sendfile.h'
	cfgtest_interface_presence 'sendfile'

	# getrandom: easier to simply test,
	# than to test whether we need to test
	# (and then test).
	mb_cfgtest_headers='sys/syscall.h'

	if cfgtest_decl_presence 'SYS_getrandom'; then
		cfgtest_cflags_append '-DHAVE_GETRANDOM_SYSCALL'
	fi

	# ncurses
	cfgtest_newline
	cfgtest_comment 'ncurses/ncursesw'
	mb_cfgtest_headers='ncurses.h'

	if [ $mb_cfgtest_cfgtype = 'target' ]; then
		mb_cfgtest_makevar='CFLAGS_NCURSES'
	else
		mb_cfgtest_makevar='NATIVE_CC_CFLAGS'
	fi

	cfgtest_unit_header_presence 'curses.h'
	cfgtest_unit_header_presence 'ncurses.h'

	cfgtest_unit_header_presence 'ncurses/panel.h'  && mb_panel_wrapper='yes'
	cfgtest_unit_header_presence 'ncursesw/panel.h' && mb_panel_wrapper='yes'

	if cfgtest_unit_interface_presence 'is_term_resized'; then
		cfgtest_makevar_append '-DHAVE_CURSES_IS_TERM_RESIZED'
	fi

	if cfgtest_unit_interface_presence 'resizeterm'; then
		cfgtest_makevar_append '-DHAVE_CURSES_RESIZETERM'
	fi

	if cfgtest_unit_interface_presence 'resize_term'; then
		cfgtest_makevar_append '-DHAVE_CURSES_RESIZE_TERM'
	fi

	# ncursesw
	if cfgtest_unit_interface_presence 'mvwget_wch'; then
		cfgtest_makevar_append '-DHAVE_NCURSESW'
	fi

	# ncurses: python refers to members of typedef struct _win_st WINDOW
	cfgtest_makevar_append '-DNCURSES_INTERNALS'

	# <panel.h>
	if [ -n "$mb_panel_wrapper" ]; then
		cfgtest_makevar_append '-I$(PROJECT_DIR)/wrappers'
		unset mb_panel_wrapper
	fi

	# ncurses libs (common part)
	mb_ncurses_libs='-lpanelw -lncursesw'
	mb_ncurses_tinfo='-ltinfo'

	if cfgtest_library_presence $mb_ncurses_tinfo; then
		mb_ncurses_libs="$mb_ncurses_libs $mb_ncurses_tinfo"
	fi
}


cfgdefs_perform_target_tests()
{
	# init
	cfgtest_target_section

	# common tests
	cfgdefs_perform_common_tests

	# ncurses libs
	mb_cfgtest_makevar='LDFLAGS_NCURSES_LIBS'
	cfgtest_makevar_append $mb_ncurses_libs

	mb_cfgtest_makevar='LDFLAGS_NCURSES'
	cfgtest_makevar_append \
		'-Wl,--as-needed $(LDFLAGS_NCURSES_LIBS)' \
		'-Wl,--no-as-needed'

	mb_cfgtest_makevar='LDFLAGS_NCURSES_STATIC'
	cfgtest_makevar_append '$(LDFLAGS_NCURSES)'

	# ndbm
	cfgtest_newline
	cfgtest_comment 'ndbm'
	cfgtest_header_presence 'ndbm.h'

	# openssl
	cfgtest_newline
	cfgtest_comment 'openssl/libressl'

	mb_cfgtest_headers='openssl/x509.h'

	if cfgtest_interface_presence 'X509_NAME_ENTRY_set'; then
		cfgtest_cflags_append '-DOPENSSL_VERSION_1_1'
	fi

	# tcl/tk libc
	cfgtest_newline
	cfgtest_comment 'tcl/tk'

	for mb_tcltk_ver in 8.9 8.8 8.7 8.6 8.5; do
		if [ -z "$mb_tcltk_libs" ]; then
			mb_tcltk_libs="-ltk$mb_tcltk_ver -ltcl$mb_tcltk_ver"
			cfgtest_library_presence $mb_tcltk_libs \
				|| mb_tcltk_libs=''
		fi
	done

	mb_cfgtest_makevar='LDFLAGS_TCLTK_LIBS'
	cfgtest_makevar_append "$mb_tcltk_libs"

	# pretty cfgdefs.mk
	cfgtest_newline
}


cfgdefs_perform_native_tests()
{
	# init
	cfgtest_native_section

	# common tests
	cfgdefs_perform_common_tests

	# ncurses libs
	cfgtest_ldflags_append $mb_ncurses_libs

	# pretty cfgdefs.mk
	cfgtest_newline
}


# cfghost
cfgdefs_set_cfghost_flavors

# python version info
cfgdefs_detect_python_version

# cfgdefs.in --> cfgdefs.mk
cfgdefs_output_custom_defs

# target-specific tests
cfgdefs_perform_target_tests

# native system tests
cfgdefs_perform_native_tests

# all done
return 0
