#!/bin/bash
#
# Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
# ===========================================================================
# (c) Copyright IBM Corp. 2017, 2025 All Rights Reserved
# ===========================================================================

if test "x$1" != xCHECKME; then
  echo "WARNING: Calling the wrapper script directly is deprecated and unsupported."
  echo "Not all features of configure will be available."
  echo "Use the 'configure' script in the top-level directory instead."
  TOPDIR=$(cd $(dirname $0)/../.. > /dev/null && pwd)
else
  # Now the next argument is the absolute top-level directory path.
  # The TOPDIR variable is passed on to configure.ac.
  TOPDIR="$2"
  # Remove these two arguments to get to the user supplied arguments
  shift
  shift
fi

# Force autoconf to use bash. This also means we must disable autoconf re-exec.
export CONFIG_SHELL=$BASH
export _as_can_reexec=no

conf_script_dir="$TOPDIR/common/autoconf"

if [ "$CUSTOM_CONFIG_DIR" = "" ]; then
  conf_custom_script_dir="$TOPDIR/jdk/make/closed/autoconf"
else
  conf_custom_script_dir="$CUSTOM_CONFIG_DIR"
fi

CURRENT_DIR=`pwd`
if test "x$CURRENT_DIR" = "x$TOPDIR"; then
  # We are running configure from the src root.
  # Create '.configure-support' under $TOPDIR/build.
  build_support_dir="$TOPDIR/build/.configure-support"
elif test "x$CURRENT_DIR" = "x$CUSTOM_ROOT"; then
  # We are running configure from the custom root.
  # Create '.configure-support' under $CUSTOM_ROOT/build.
  build_support_dir="$CUSTOM_ROOT/build/.configure-support"
else
  # We are running configure from outside of the src dir.
  # Create 'build_support_dir' in the current directory.
  build_support_dir="$CURRENT_DIR/configure-support"
fi

generated_script="$build_support_dir/generated-configure.sh"

###
### Ensure that the generated configure script is up-to-date.
###

run_autogen_or_fail() {
  echo "Generating $generated_script"

  AUTOCONF="`which autoconf 2> /dev/null | grep -v '^no autoconf in'`"

  if test "x${AUTOCONF}" = x; then
    echo "You need autoconf installed to be able to generate the configure script"
    echo "Error: Cannot find autoconf" 1>&2
    exit 1
  fi

  autoconf_version=`$AUTOCONF --version | head -1`
  echo "Using autoconf at ${AUTOCONF} [$autoconf_version]"

  if test "x$CUSTOM_CONFIG_DIR" = "x"; then
    custom_script_dir="$TOPDIR/jdk/make/closed/autoconf"
  else
    custom_script_dir=$CUSTOM_CONFIG_DIR
  fi

  custom_hook=$custom_script_dir/custom-hook.m4

  if test -e $custom_hook; then
    # Generate configure script with custom hooks compiled in.
    custom_patcher='sed -e "s|#CUSTOM_AUTOCONF_INCLUDE|m4_include([$custom_hook])|"'
  else
    custom_patcher='cat'
  fi

  mkdir -p $build_support_dir

  # Call autoconf but replace the "magic" variable in configure.ac if requested.
  cat $conf_script_dir/configure.ac | eval $custom_patcher | \
      ${AUTOCONF} -W all -I$conf_script_dir - > $generated_script
  rm -rf autom4te.cache

  # Sanity check
  if test ! -s $generated_script; then
    echo "Error: Failed to generate runnable configure script" 1>&2
    rm -f $generated_script
    exit 1
  fi
}

check_autoconf_timestamps() {
  for file in $conf_script_dir/configure.ac $conf_script_dir/*.m4 ; do
    if test $file -nt $generated_script; then
      echo "Runnable configure script is not up to date"
      run_autogen_or_fail
      return
    fi
  done

  if test -d $conf_custom_script_dir; then
    # If custom source configure is available, make sure it is up-to-date as well.
    for file in $conf_custom_script_dir/*.m4; do
      if test $file -nt $generated_script; then
        echo "Runnable configure script is not up to date"
        run_autogen_or_fail
        break
      fi
    done
  fi
}

if test -e $generated_script; then
  check_autoconf_timestamps
else
  echo "Runnable configure script is not present"
  run_autogen_or_fail
fi

# Autoconf calls the configure script recursively sometimes.
# Don't start logging twice in that case
if test "x$conf_debug_configure" = xtrue; then
  conf_debug_configure=recursive
fi

###
### Process command-line arguments
###

# Returns a shell-escaped version of the argument given.
function shell_quote() {
  if [[ -n "$1" ]]; then
    # Uses only shell-safe characters?  No quoting needed.
    # '=' is a zsh meta-character, but only in word-initial position.
    if [[ "$1" =~ ^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.:,%/+=_-]+$ && ! "$1" =~ ^= ]]; then
      quoted="$1"
    else
      if [[ "$1" =~ [\'!] ]]; then
        # csh does history expansion within single quotes, but not
        # when backslash-escaped!
        local quoted_quote="'\\''" quoted_exclam="'\\!'"
        word="${1//\'/${quoted_quote}}"
        word="${1//\!/${quoted_exclam}}"
      fi
      quoted="'$1'"
    fi
    echo "$quoted"
  fi
}

# Add default OpenJ9 closed extensions: decode OPENJDK_TAG from closed/openjdk-tag.gmk.
openjdk_tag="$(sed -n -e 's/[\t ]//g' -e 's/^OPENJDK_TAG:=jdk8u//p' < "$TOPDIR/closed/openjdk-tag.gmk")"
build_update_version="$(echo $openjdk_tag | sed -e 's/-b[0-9][0-9]*$//')"
jdk_build_number="$(echo $openjdk_tag | sed -e 's/^[0-9][0-9]*-b//')"

conf_milestone=
conf_processed_arguments=("--with-custom-make-dir=$TOPDIR/closed/make" "--with-update-version=$build_update_version")
conf_quoted_arguments=()
conf_openjdk_target=

for conf_option
do

  # Process (and remove) our own extensions that will not be passed to autoconf
  case $conf_option in
    --openjdk-target=*)
      conf_openjdk_target=`expr "X$conf_option" : '[^=]*=\(.*\)'`
      ;;
    --with-milestone=*)
      conf_milestone=`expr "X$conf_option" : '[^=]*=\(.*\)'`
      conf_processed_arguments=("${conf_processed_arguments[@]}" "$conf_option") ;;
    --debug-configure)
      if test "x$conf_debug_configure" != xrecursive; then
        conf_debug_configure=true
        export conf_debug_configure
      fi
      ;;
    *)
      conf_processed_arguments=("${conf_processed_arguments[@]}" "$conf_option")
      ;;
  esac

  # Store all variables overridden on the command line
  case $conf_option in
    [^-]*=*)
      # Add name of variable to CONFIGURE_OVERRIDDEN_VARIABLES list inside !...!.
      conf_env_var=`expr "x$conf_option" : 'x\([^=]*\)='`
      CONFIGURE_OVERRIDDEN_VARIABLES="$CONFIGURE_OVERRIDDEN_VARIABLES!$conf_env_var!"
      ;;
  esac

  # Save the arguments, intelligently quoted for CONFIGURE_COMMAND_LINE.
  case $conf_option in
    *=*)
      conf_option_name=`expr "x$conf_option" : 'x\([^=]*\)='`
      conf_option_name=$(shell_quote "$conf_option_name")
      conf_option_value=`expr "x$conf_option" : 'x[^=]*=\(.*\)'`
      conf_option_value=$(shell_quote "$conf_option_value")
      conf_quoted_arguments=("${conf_quoted_arguments[@]}" "$conf_option_name=$conf_option_value")
      ;;
    *)
      conf_quoted_arguments=("${conf_quoted_arguments[@]}" "$(shell_quote "$conf_option")")
      ;;
  esac

  # Check for certain autoconf options that require extra action
  case $conf_option in
    -build | --build | --buil | --bui | --bu |-build=* | --build=* | --buil=* | --bui=* | --bu=*)
      conf_legacy_crosscompile="$conf_legacy_crosscompile $conf_option" ;;
    -target | --target | --targe | --targ | --tar | --ta | --t | -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
      conf_legacy_crosscompile="$conf_legacy_crosscompile $conf_option" ;;
    -host | --host | --hos | --ho | -host=* | --host=* | --hos=* | --ho=*)
      conf_legacy_crosscompile="$conf_legacy_crosscompile $conf_option" ;;
    -help | --help | --hel | --he | -h)
      conf_print_help=true ;;
  esac
done

# Save the quoted command line
CONFIGURE_COMMAND_LINE="${conf_quoted_arguments[@]}"

if test "x$conf_legacy_crosscompile" != "x"; then
  if test "x$conf_openjdk_target" != "x"; then
    echo "Error: Specifying --openjdk-target together with autoconf"
    echo "legacy cross-compilation flags is not supported."
    echo "You specified: --openjdk-target=$conf_openjdk_target and $conf_legacy_crosscompile."
    echo "The recommended use is just --openjdk-target."
    exit 1
  else
    echo "Warning: You are using legacy autoconf cross-compilation flags."
    echo "It is recommended that you use --openjdk-target instead."
    echo ""
  fi
fi

if test "x$conf_openjdk_target" != "x"; then
  conf_build_platform=`sh $conf_script_dir/build-aux/config.guess`
  conf_processed_arguments=("--build=$conf_build_platform" "--host=$conf_openjdk_target" "--target=$conf_openjdk_target" "${conf_processed_arguments[@]}")
fi

# If milestone "fcs" RELEASE build then set build-number
if test "x$conf_milestone" = "xfcs"; then
  conf_processed_arguments=("--with-build-number=$jdk_build_number" "${conf_processed_arguments[@]}")
fi

# Make configure exit with error on invalid options as default.
# Can be overridden by --disable-option-checking, since we prepend our argument
# and later options override earlier.
conf_processed_arguments=("--enable-option-checking=fatal" "${conf_processed_arguments[@]}")

###
### Call the configure script
###
echo "Running generated-configure.sh"
conf_script_to_run=$generated_script

if test "x$conf_debug_configure" != x; then
  # Turn on shell debug output if requested (initial or recursive)
  set -x
fi

# Now transfer control to the script generated by autoconf. This is where the
# main work is done.
conf_logfile=./configure.log
(exec 3>&1 ; (. $conf_script_to_run "${conf_processed_arguments[@]}" 2>&1 1>&3 ) | tee -a $conf_logfile 1>&2 ; exec 3>&-) | tee -a $conf_logfile

conf_result_code=$?
###
### Post-processing
###

if test $conf_result_code -eq 0; then
  if test "x$conf_print_help" = xtrue; then
    cat <<EOT

Additional (non-autoconf) OpenJDK Options:
  --openjdk-target=TARGET cross-compile with TARGET as target platform
                          (i.e. the one you will run the resulting binary on).
                          Equivalent to --host=TARGET --target=TARGET
                          --build=<current platform>
  --debug-configure       Run the configure script with additional debug
                          logging enabled.

EOT

    # Print list of toolchains. This must be done by the autoconf script.
    ( CONFIGURE_PRINT_TOOLCHAIN_LIST=true . $conf_script_to_run PRINTF=printf )

    cat <<EOT

Please be aware that, when cross-compiling, the OpenJDK configure script will
generally use 'target' where autoconf traditionally uses 'host'.

Also note that variables must be passed on the command line. Variables in the
environment will generally be ignored, unlike traditional autoconf scripts.
EOT
  fi
else
  echo configure exiting with result code $conf_result_code
fi

exit $conf_result_code
