#!/bin/sh
#
# Copyright 2009-2021
# Kaz Kylheku <kaz@kylheku.com>
# Vancouver, Canada
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
#    list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#
# The #!/bin/sh might be some legacy piece of junk, not even up to 1990 POSIX.2
# spec. So the first step is to look for a better shell in some known places
# and re-execute ourselves with that interpreter, unless there is evidence we
# are already running in a usable shell.
#

while true ; do
  # we have already recursed into a desired shell
  if test "x$txr_shell" != x ; then
    break
  fi

  # If PS4 is set to "+ ", we are probably running on a good shell: GNU
  # Bash sets it like this, as does late-model Ash, Dash, Korn Shell 93,
  # and the XPG shell on Solaris 10. Zsh sets PS4 to "+ " this in its
  # POSIX mode, which handles our script, but to some other value in its
  # regular mode which doesn't handle our script.
  if test "x$PS4" = "x+ " ; then
    break
  fi

  # Slow path: find a suitable shell.
  # First choice is $CONFIG_SHELL, a convention from GNU Autoconf.
  for shell in "$CONFIG_SHELL" \
               /bin/bash /usr/bin/bash /usr/local/bin/bash \
               /bin/dash /usr/bin/dash /usr/local/bin/dash \
               /bin/ksh /usr/bin/ksh /usr/local/bin/ksh \
               /usr/xpg4/bin/sh
  do
    if test -x "$shell" ; then
       txr_shell=$shell
       break
    fi
  done

  if test "x$txr_shell" = x ; then
    echo "No known modern shell found; sticking with this one."
    break;
  fi

  # we export txr_shell because it acts as a flag indicating the recursed case
  export txr_shell
  echo "Re-executing using $txr_shell"
  exec "$txr_shell" $0 ${@+"$@"}
  break
done

set -u

if [ -n "${txr_shell+y}" ] ; then
  printf "Now running in %s shell\n" $txr_shell
else
  printf "Running in original shell.\n"
fi

#
# Save command line in a way that can be re-run.
#

cmdline=
for arg in "$0" ${@+"$@"} ; do
  [ -n "$cmdline" ] && cmdline="$cmdline "
  case $arg in
  *"'"* )
    case $arg in
    *'"'* | *'$'* )
      cmdline="$cmdline'$(printf "%s" "$arg" | sed -e "s/'/'\\\\''/g")'"
      ;;
    * )
      cmdline="$cmdline\"$arg\""
      ;;
    esac
    ;;
  *'"'* | *['$*?[(){};&|<>#']* | '~'* )
    cmdline="$cmdline'$arg'"
    ;;
  *' '* | *'    '* )
    cmdline="$cmdline\"$arg\""
    ;;
  * )
    cmdline="$cmdline$arg"
    ;;
  esac
done

#
# Use the POSIX locale to suppress monkey business in the utilities
# 

export LC_ALL="C"
export LANG="C"

#
# Establish default values for any variables that are not specified
# on the command line. The default derivations from prefix are in
# Make syntax. They go verbatim into the generated config.make.
# This way they can be overridden more flexibly at make time.
#

#
# non-config
#
help=

#
# config
#
build_in_srcdir=
prefix='/usr/local'
install_prefix=
bindir='bin'
datadir='share/txr'
mandir='share/man'
maintainer=
parallelmake=
parallelmake_given=
make=
cross=
compiler_prefix=
ccname='$(CC)'
cc='$(cross)$(compiler_prefix)$(ccname)'
gcc_version=
broken128=
do_nopie=y
cplusplus=
intptr=
exe=
tool_prefix=
lexname_given=
lexname=
lex_given=
lex='$(cross)$(tool_prefix)$(lexname)'
yaccname_given=
yaccname='' # test tries $(YACC) first
yacc='$(cross)$(tool_prefix)$(yaccname)'
yacc_given=
nm='$(cross)$(tool_prefix)nm'
opt_flags='-O2 -fno-stack-protector'
lang_flags='-D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200112 -D_GNU_SOURCE'
diag_flags="-Wall -Wextra -Werror=implicit-function-declaration \
           -Werror=missing-prototypes -Werror=strict-prototypes \
           -Werror=old-style-definition"
debug_flags=-g
debug_only_flags=-DTXR_DEBUG
debug_also=
inline=
platform_cflags=
remove_flags=
lex_dbg_flags=
conf_ldflags=
conf_ldlibs=
platform_ldflags=
platform_ldlibs=
txr_dbg_opts=--gc-debug
valgrind=
extra_debugging=
debug_support=y
gen_gc=y
small_mem=
have_dbl_decimal_dig=
have_unistd=
have_sys_stat=
have_sys_types=
have_sys_time=
have_strerror_r=
have_makedev=
have_syslog=
have_glob=
have_ftw=
have_windows_h=
have_windres=
have_posix_sigs=
have_sockets=
have_git=
have_pwuid=
have_grgid=
have_alloca=
have_termios=
have_winsize=
termios_define=
have_pkgconfig=
libffi_cflags=
darwin_target=
android_target=
build_id=

#
# Parse configuration variables
#
while [ $# -gt 0 ] ; do
  case $1 in
  --no-* | --no_* )
    var=${1#--no?}
    val=
    ;;
  --*=* )
    var=${1%%=*}
    var=${var#--}
    val=${1#*=}
    ;;
  --*= )
    var=${1%%=*}
    var=${var#--}
    val=
    ;; --* )
    var=${1#--}
    val=y
    ;;
  *=* )
    var=${1%%=*}
    val=${1#*=}
    ;;
  *= )
    var=${1%%=*}
    val=
    ;;
  * )
    printf "$0: '$1' doesn't look like a configuration variable assignment\n"
    printf "$0: use --help to get help\n"
    exit 1
  esac

  var=$(echo "$var" | tr - _)

  if ! echo $var | grep -q -E '^[A-Za-z_][A-Za-z0-9_]*$' ; then
    printf "$0: '$var' isn't a proper configuration variable name\n"
    exit 1
  fi

  eval "var_exists=\${$var+y}"

  if [ "$var_exists" != y ] ; then
    printf "$0: nonexistent option: '%s'\n" "$1"
    exit 1
  fi

  eval "$var='$(printf "%s" "$val" | sed -e "s/'/'\\\\''/g")'"

  eval "var_given_exists=\${${var}_given+y}"

  if [ "$var_given_exists" = y ] ; then
    eval "${var}_given=y"
  fi

  shift
done

#
# If --help was given (or --help=<nonempty> or help=<nonempty>) then
# print help and exit. The termination status is failed, to indicate
# that configuration was not done.
#

if [ -n "$help" ] ; then
cat <<!

usage: $0 { variable=value }*

The configure script prepares txr program for compilation and installation.
To configure a program means to establish the values of make variables
which influence how the software is built, where it is installed.
These variables can also influence what features are present in the
software, and can determine various defaults for those behaviors which are
dynamically configurable when the software is run.

Configuration variables are recorded in a file called config.make.
This is a GNU makefile, and consequently uses the GNU make syntax. It is
included in the main Makefile by an include statement.

The configuration command line is recorded in a script called reconfigure.
To re-run the configure script again with the same parameters, without
repeating those parameters, run the ./reconfigure script.

The configure script is flexible. It allows variables to be entered in any
of these forms:

Canonical:

   variable=value      Defines the given variable as having the given value.
   variable=           Defines the variable as having an empty value.
                       An empty value serves as Boolean false.

Long-option style:

   --variable=value    Same as 'variable=value', but resembles a GNU-style
                       long option.
   --variable          Same as 'variable=y'.
   --no-variable       Same as 'variable='.

No variables are required. The configure script establishes default values
for any variables which are needed by the build, but which are not specified
on the command line.

After running $0, check that the config.make contents are sane.

The following variables are supported.  Note that make variable syntax may
be used in paths. Default values are shown in [square brackets].

Variables are case-sensitive, but underscores and dashes are interchangeable.

maintainer [$maintainer]

  This a Boolean variable. If set to 'y', then it it specifies maintainer
  mode, otherwise the build is configured for user mode. In maintainer mode,
  the scanner and parser generator tools are expected to be available.
  In user mode, the shipped parser and scanner are used. Changes to
  the parser.l and parser.y files will have no effect. In maintainer mode,
  also, c90 is used if compiling the code as C.

parallelmake [$parallelmake]

  Boolean. If set to 'y', it specifies that parallel building with make -j
  is permitted. Otherwise the Makefile asserts no parallelism with
  a .NOTOPARALLEL: directive. The above maintainer mode also implies
  parallel building being permited.

prefix [$prefix]

  Specifies root directory where the software will ultimately be installed and
  run from.

install-prefix [$install_prefix]

  Specifies an extra path prefix that will be prepended to all paths during
  installation, which allows the software to be installed in a temporary
  directory for packaging. This variable becomes the \$(DESTDIR)
  variable in the config.make makefile.

bindir [$bindir]

  Specifies where the program executable will be installed, as a relative
  path from the prefix.

datadir [$datadir]

  Specifies where read-only program data is to be stored, as a relative
  path from the prefix.

mandir [$mandir]

  Specifies the directory where to install man pages, as a relative
  path from the prefix.

cross [$cross]

  Specifies the root of a cross-compiling toolchain.
  This becomes the \$(cross) variable in the config.make makefile, and by
  default will be added as a prefix to all of the toolchain commands.
  It should include the trailing slash, unless the \$compiler_prefix
  and \$tool_prefix variables take care of this by providing a leading slash.
  If this variable is set, ccname should also be set; the default
  ccname doesn't make sense in that case.

compiler-prefix [$compiler_prefix]

  Specifies a prefix to be added to the compiler command.
  This is added to the \$(cross) prefix. This can include some path name
  components, and a name fragment. For instance, if
  \$cross is "/cross/toolchain/" and \$compiler_prefix is
  "bin/mips-linux-" then the compiler command, unless otherwise
  specified, will be "/cross/toolchain/bin/mips-linux-gcc".
  If this variable is set, ccname should also be set; the default
  ccname doesn't make sense in that case.

ccname [$ccname]

  Specifies just the name of the compiler front-end program, without the path.
  The following variable, cc, specifies the full name.
  The default value is the \$(CC) predefined make variable.

cc [$cc]

  Specifies the name of the toolchain front-end driver command to use for
  compiling C sources to object files, and for linking object files to
  executables. This becomes the TXR_CC variable in config.make.
  Note that cross and compiler_prefix are empty by default and
  and so this expands to just ccname.

intptr [$intptr]

  Specifies the name of the C integer type wide enough such that a pointer
  value can be converted to it. If this is blank, the configure script
  will try to auto detect it.

inline [$inline]

  Specifies the syntax for defining an inline function, in such
  a way that the function definition can be included into multiple
  translation units without clashes.

  If blank, an attempt is made to auto-detect this which
  falls back on "static".

tool-prefix [$tool_prefix]

  Specifies a prefix to be added to tool commands other than the
  compiler, like lex and yacc, in addition to \$cross.

lexname [$lexname]

  Specifies just the name of the lex program without the path.
  The following variable, lex, specifies the full name.
  If blank, the choice lex program will be auto-detected.

lex [$lex]

  Specifies the program to use for compiling lex scanners to C.
  This must be compatible with GNU flex, since flex extensions are used.

yaccname [$yaccname]

  Specifies just the name of the yacc program without the path.
  The following variable, yacc, specifies the full name.
  If blank, the choice yacc program will be auto-detected.

yacc [$yacc]

  Specifies the program to use for compiling yacc scanners to C.

nm [$nm]

  Specifies the nm program for dumping symbols from an object file.

opt-flags [$opt_flags]

  Specifies optimization flags to use for compiling and linking
  C sources. Note that these are in addition to any CFLAGS
  passed in the environment or on the make command line.

lang-flags [$lang_flags]

  Specifies compiler flags which control the C language dialect and standard
  conformance in the language and header files. The txr program is written
  in C90, and requires POSIX and possibly other extensions.

diag-flags [$diag_flags]

  Specifies compiler flags for obtaining extra diagnostics.

debug-flags [$debug_flags]

  Specifies flags for requesting that debugging information be
  retained in the compile and link. These flags are applied
  to optimized and debugging targets.

debug-only-flags [$debug_only_flags]

  Specifies compiler flags which only apply to debugging
  targets.

debug-also [$debug_also]

  Specifies that a debugging version of TXR is to be built at the
  same time. This means that "make" will always update two sets
  of object files compiled with different optimization flags,
  and produce two binaries: txr and txr-dbg.

platform-cflags [$platform_cflags]

  Specify additional compiler flags for anything else, such as CPU tuning,
  target ABI selection, code generation options, et cetera.

platform-ldflags [$platform_ldflags]

  Specify additional linker flags for anything else, such as hardening,
  linking as needed, et cetera.  Flas specifying librariews (-l options)
  should be specified using platform-ldlibs instead.  Note that these are in
  addition to any LDFLAGS from the environment or make command line.

platform-ldlibs [$platform_ldlibs]

  Specify additional linker flags for just libraries (-l options)
  linking as needed, et cetera. Note that these are in addition to
  any LDLIBS from the environment or make command line.

remove-flags [$remove_flags]

  This is a negative otpion. Any flags mentioned in this variable
  will be removed from any of the other compiler flags options above.
  The flags may contain GNU Make patterns.

lex-dbg-flags [$lex_dbg_flags]

  Specifies debug flags to be passed to lex, perhaps to generate a debugging
  scanner.

txr-dbg-opts [$txr_dbg_opts]

  Specifies debug flags to pass to the txr program during the execution
  of "make tests".

valgrind [$valgrind]

  Use --valgrind to to build txr with valgrind integration.
  Valgrind integration means that when the program is running under valgrind,
  it advises valgrind about stack memory locations accessed by the garbage
  collector, to suppress diagnostics about uninitialized accesses.

extra-debugging [$extra_debugging]

  Use --extra_debugging to configure some additional debugging features,
  which incur a run-time penalty.

gen-gc [$gen_gc]

  Use --no-gen-gc to disable the generational garbage collector which
  is now enabled by default.

  When disabled, the garbage collector performs a full object traversal and
  sweep on each garbage collection.

small-mem [$small_mem]

  Use --small-mem to make the memory management use less memory,
  for embedded systems with less RAM, at the possible cost of some
  run-time penalty. Objects are allocated in smaller blocks,
  and certain global book-keeping arrays in the generational garbage
  collector are smaller, resulting in more frequent collections.

build-id [$build_id]

  This option specifies the value of the build_id make variable.
  The argument is GNU make syntax which calculates a string
  that is inserted into the TXR executable. The string is reproduced
  by reproduced using the txr --build-id. The default is that there
  no build-id, and the --build-id option produces empty output.

  If the argument value "git" is given, then the value is replaced
  by syntax which which takes value of the output of the command
  "git describe --tags --dirty",
  executed in the source directory. This is recalculated each time
  the txr.c source file is compiled.

  The build_id variable can be overridden from the make command line.

!
  exit 1
fi

#
# Tentatively save configuration in config.log
#
rm -rf reconfigure
cat > reconfigure <<!
#!/bin/sh
#
# Configured on $(date) using:

$cmdline

# The above did not complete.
!

chmod a+x reconfigure


#
# Variables are read, --help wasn't given, so let's configure!
#


txr_ver=266

#
# The all important banner.
#

if [ $txr_ver ] ; then
  banner_text=$(printf " Configuring txr %s " "$txr_ver")
else
  banner_text=" Configuring txr (unknown version) "
fi
banner_box=$(printf "%.${#banner_text}s\n" \
             "-------------------------------------------")
printf "+%s+\n|%s|\n+%s+\n" $banner_box "$banner_text" $banner_box

#
# From here on in, we bail if any command fails.
#

set -e

#
# Check for GNU make
#

printf "Checking for GNU Make ... "

if [ -z "$make" ] ; then
  for make in make gmake ; do
    output=$($make --version 2> /dev/null) || true
    set -- $output

    if [ $# -lt 3 ] || [ $1 != "GNU" -o $2 != "Make" ] ; then
      continue
    fi
    break
  done
fi

if [ $# -lt 3 ] ; then
  printf "missing\n"
  exit 1
fi

make_version=$3

save_ifs=$IFS ; IFS=. ; set -- $make_version ; IFS=$save_ifs

if [ $1 -lt 3 -o \( $1 -eq 3 -a $2 -lt 81 \) ] ; then
  printf "too old (%s found, 3.81 or newer needed)\n" $make_version
  exit 1
else
  printf "yes (%s found)\n" $make_version
fi

#
# Verify sanity of --prefix and other directories.
#

printf "Checking installation paths:\n"

for name in bindir datadir mandir; do
  eval path="\$install_prefix\$prefix/\${$name}"
  printf "\$(install_prefix)\$(prefix)/\$%s=%s ... " $name "$path"
  test_access=y
  case "$path" in
  " "* | *" "* | *" " )
    printf "incorrect (contains spaces)\n"
    exit 1
    ;;
  -* )
    printf "incorrect (resembles a command option)\n"
    exit 1
    ;;
  *'$('* )
    # It's a make expression; can't test it
    test_access=
    ;;
  /* )
    ;;
  * )
    printf "incorrect (must be absolute path)\n"
    exit 1
    ;;
  esac

  if [ $test_access ] ; then
    test_prefix=$path

    while true ; do
      if [ -e $test_prefix ] ; then
      if [ ! -d $test_prefix ] ; then
        printf "incorrect ('%s' is not a directory)!\n" $test_prefix
        exit 1
      fi
      if [ ! -w $test_prefix ] ; then
        printf "okay\n  (but no write access to '%s'\n" $test_prefix

        printf "   so '$make install' will require root privileges)\n"
      else
        printf "okay\n"
      fi
      break
      fi
      test_prefix=$(dirname $test_prefix)
    done
  else
    printf "okay\n  (make variable derivation)\n"
  fi
done

#
# First, we have to figure out whether we are configured straight
# in the source directory, or whether we are in a separate build directory.
# In the latter case, we set up a symbolic link to the Makefile.
#
source_dir="$(dirname $0)"

#
# If building in a separate directory, establish top_srcdir as
# an absolute path to the source directory, with a trailing slash.
# Otherwise top_srcdir is blank.
#

if [ "$source_dir" = "." ] ; then
  top_srcdir=""
else
  top_srcdir="$(cd "$source_dir" ; pwd -P)"/
fi

printf "Checking source directory \"%s\" ..." "$top_srcdir"

lndir()
{
  fromdir=$1
  todir=${2%/}
  abs=${fromdir%${fromdir#/}}

  find "$fromdir" \( -type f -o -type d \) | while read frompath ; do
    topath=${frompath#$fromdir}
    topath=${topath#/}
    [ -n "$topath" ] || topath="."
    if [ -f "$frompath" ] ; then
      if [ $abs ] ; then
        ln -sf "$frompath" "$todir/$topath"
      else
        old_IFS=$IFS
        IFS=/
        set -- $todir/$topath
        IFS=$old_IFS
        dots=""
        while [ $# -gt 0 ] ; do
          [ $1 = "." ] || dots="$dots../"
          shift
        done
        rm -f "$todir/$topath"
        ln -sf "$dots$frompath" "$todir/$topath"
      fi
    else
      mkdir -p "$todir/$topath"
    fi
  done
}

inode()
{
  set -- $(ls -idL "$1")
  printf "%s\n" "$1"
}

case "$top_srcdir" in
" "* | *" "* | *" " )
  printf " bad (contains spaces)\n"
  exit 1
  ;;
* )
  printf " okay\n"
  ;;
esac

if [ $(inode "$source_dir") != $(inode ".") ] ; then
  for x in Makefile ; do
    printf "Symlinking %s -> $source_dir/%s\n" $x $x
    ln -sf "$source_dir/$x" .
  done
  for x in stdlib tests; do
    printf "Tree symlinking %s -> $source_dir/%s\n" $x $x
    lndir $source_dir/$x $x
  done
else
  printf "** Note: it's recommended to build in a separate directory\n"
  build_in_srcdir=y
fi

printf "Are we using a C++ compiler ..."

case $ccname in
*'++' | *'$(CXX)' )
   cplusplus=y
   ;;
esac

case $cc in
*'++' | '$(CXX)' )
  cplusplus=y
  ;;
esac

if [ $cplusplus ] ; then
   printf "yes\n"
   set -- $diag_flags
   diag_flags=''
   for flag in "$@" ; do
     case $flag in
       *=implicit-function-declaration | \
       *=missing-prototypes | \
       *=old-style-* | \
       *=strict-prototypes )
       continue
       ;;
     esac
     diag_flags="$diag_flags $flag"
   done
   diag_flags=${diag_flags# }
   lang_flags="-std=c++98 $lang_flags"
else
   printf "no\n"
   if [ $maintainer ] ; then
     lang_flags="-ansi $lang_flags"
   else
     lang_flags="-std=c99 $lang_flags"
   fi
fi

gen_config_make()
{
  cat > config.make <<!
#
# Make include file automatically generated by $0.
# Changes to this file are lost when the above is re-run.
#

${txr_shell:+# Shell used by make for running recipes; this
# is the as the shell we chose for the configure script,
# derived from the txr_shell variable.
SHELL := $txr_shell}

txr_ver := $txr_ver

# is this configuration in maintainer mode
maintainer := $maintainer

# absolute path to source code directory or blank if
# not building in a separate directory
top_srcdir := $top_srcdir

# build directory is top_srcdir
build_in_srcdir = $build_in_srcdir

# ultimate installation prefix, where the
# application will be run.
prefix := $prefix

# packaging installation prefix, where the
# application may be temporarily installed
# for creating pre-compiled packages,
# e.g. for an operating system distro.
DESTDIR := $install_prefix

# relative path from prefix to datadir
bindir_rel := $bindir

# executable directory
bindir = \$(prefix)/\$(bindir_rel)

# read-only data directory
datadir = \$(prefix)/$datadir

# man page directory
mandir = \$(prefix)/$mandir

# cross compiler toolchain root directory
cross := $cross

# compiler name
ccname = $ccname

# name of lex program
lexname = $lexname

# name of yacc program
yaccname = $yaccname

# prefix for compiler command
compiler_prefix := $compiler_prefix

# prefix for non-compiler toolchain commands
tool_prefix := $tool_prefix

# build_id
$(gitcmd='git describe --tags --dirty';
  if [ "$build_id" = "git" ] ; then
     if [ $build_in_srcdir ] ; then
       printf 'build_id ?= $(shell %s)\n' "$gitcmd"
     else
       printf 'build_id ?= $(shell cd $(top_srcdir); %s)\n' "$gitcmd"
     fi
  else
     printf 'build_id = %s\n' "$build_id"
  fi)
build_id_exp := \$(build_id)

# do we compile in syslog support?
have_syslog := $have_syslog

# do we compile in glob support?
have_glob := $have_glob

# do we compile in ftwsupport?
have_ftw := $have_ftw

# do we modern posix signal handling?
have_posix_sigs := $have_posix_sigs

have_sockets := $have_sockets
have_termios := $have_termios
termios_define := $termios_define

# do we compile in debug support?
debug_support := $debug_support

# allow parallel make?
parallelmake := $parallelmake

# EXE suffix
EXE := $exe

have_git := $have_git

add_win_res := $([ -n "$have_windows_h" -a -n "$have_windres" ] && echo "y")

TXR_CC := $cc
TXR_LEX := $lex
TXR_YACC := $yacc
TXR_NM := $nm

PROG := txr

OPT_FLAGS := $opt_flags
LANG_FLAGS := $lang_flags
DIAG_FLAGS := $diag_flags
DBG_FLAGS := $debug_flags
DBG_ONLY_FLAGS := $debug_only_flags
BUILD_TARGETS := $(if [ $debug_also ] ; then
                     echo '$(PROG) $(PROG)-dbg'
                   else
                     echo '$(PROG)'; fi)
PLATFORM_CFLAGS := $platform_cflags
PLATFORM_LDFLAGS := $platform_ldflags
PLATFORM_LDLIBS := $platform_ldlibs
CONF_LDFLAGS := $conf_ldflags
CONF_LDLIBS := $conf_ldlibs
REMOVE_FLAGS := $remove_flags
LEX_DBG_FLAGS := $lex_dbg_flags
TXR_DBG_OPTS := $txr_dbg_opts

LIBFFI_CFLAGS := $libffi_cflags
!
}

#
# Before doing some other tests, we need a config.make
#

printf "Generating config.make ... "
gen_config_make
printf "\n"

#
# Start config.h header
#

cat <<! > config.h
/*
 * Header file automatically generated by $0.
 * Tweaking this file may seem like a good temporary workaround
 * to some problem but you probably should fix the script
 * to do the job. In any case, be aware that you will lose your
 * changes if you re-run $0.
 */
!

#
# Perform a configure test.
# Arguments are passed through to make
#
conftest()
{
  rm -f ${exe-"conftest conftest.exe"} ${exe+"conftest$exe"}
  $make conftest ${@+"$@"} > conftest.err 2>&1 && [ -x conftest ] 
}

#
# Like conftest but make only .o
#
conftest_o()
{
  rm -f conftest.o
  $make conftest.o ${@+"$@"} > conftest.err 2>&1
}

#
# Check for git because we use it out of the Makefile
# But this is pointless if we have no git repo.
# "have_git" means we have a repo, and git.
#
if [ -d $top_srcdir.git ] ; then 
  printf "Checking whether we have git ... "

  if git --version > /dev/null 2> /dev/null ; then
    have_git=y
    printf "yes\n"
  else
    printf "missing\n"
  fi
fi

#
# Check C compiler sanity
#
printf "Checking whether your C compiler can make a simple executable ... "

cat > conftest.c <<!
#include <stdio.h>
int main(void)
{
  printf("Hello, world!\n");
  return 0;
}
!

if ! conftest ; then
  printf "failed\n"
  printf "Checking whether the failure is due to a requirement to use C99 ... "
  if conftest EXTRA_FLAGS=-std=c99 ; then
    printf "yes\n"
    lang_flags="$(echo "$lang_flags" | sed -e 's/-ansi/-std=c99/')"
  else
    printf "no\n\n"
    conftest && true
    printf "Errors from compilation: \n\n"
    cat conftest.err
    exit 1
  fi
else
  printf "okay\n"
fi

printf "Checking compiler version for various workarounds ... "

output=$($make conftest.ccver)
set -- $output
if [ "$1" = "gcc" ] ; then
  gcc_version=$3
  save_ifs=$IFS ; IFS=. ; set -- $gcc_version ; IFS=$save_ifs
  if [ $1 -lt 4 ] || [ $1 -eq 4 -a $2 -le 3 ] ; then
    broken128=y
  fi
  [ $1 -lt 5 ] && do_nopie=
elif [ "$1" = "clang" -o "$2" = "clang" ] ; then
  do_nopie=
fi

printf "done\n"

printf "Checking whether executables have that idiotic .exe suffix ... "

if ls conftest.exe > /dev/null 2>&1 ; then
  echo "yes"
  exe=.exe
else
  echo "no"
fi

rm -f conftest$exe

printf "Checking for disabling source code quoting in compiler errors ... "

cat > conftest.c <<!
#include <stdio.h>
int main(void)
{
!

if ! conftest && grep -q -E '^ +\^' conftest.err ; then
  cat > conftest.c <<!
#include <stdio.h>
int main(void)
{
return 0;
}
!
  opt=-fno-diagnostics-show-caret
  if conftest EXTRA_FLAGS=$opt ; then
    printf "needed\n"
    diag_flags="$diag_flags $opt"
  else
    printf "unable\n"
  fi
else
  printf "no need\n"
fi

#
# Check for annoying clashes from non-conforming BSD-derived systems that don't
# honor Unix/POSIX feature selection macros!
#

printf "Checking for name clashes caused by nonconforming toolchains ... "

for ident in trunc floorf random longlong_t ; do
  cat > conftest.c <<!
#include <assert.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include <setjmp.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <wchar.h>
#include <wctype.h>

struct txr_foo { int txr; } $ident;

int $ident(void);

int main(void) { return 0; }
!
  if ! conftest ; then
    printf "#define %s txr_%s\n" $ident $ident >> config.h
    have_unistd=y
  fi
done

printf "done\n"

#
# Check for idiotic behavior: extensions in C header files controlled
# by __STRICT_ANSI__ rather than things like __POSIX_SOURCE.
#

printf "Checking for proper support for feature-test macros ... "

cat > conftest.c <<!
#include <stdio.h>

int main(void)
{
   return fileno(stdin);
}
!
if conftest EXTRA_FLAGS=-Werror ; then
  printf "yes\n"
else
  printf "no\n"
  lang_flags="$lang_flags -U__STRICT_ANSI__"
  printf "Regenerating config.make ..."
  gen_config_make
  printf "done\n"
fi

#
# Detect Apple environment. We need _DARWIN_C_SOURCE.
#

printf "Checking for Apple environment ... "
if [ "$($make conftest.darwin)" = "yes" ] ; then
  printf "yes\n"
  darwin_target=y
  lang_flags="$lang_flags -D_DARWIN_C_SOURCE"
  printf "Regenerating config.make ..."
  gen_config_make
  printf "done\n"
else
  printf "no\n"
fi

if ! [ $darwin_target ] ; then
  printf "Checking for Android environment ... "

  if [ "$($make conftest.android)" = "yes" ] ; then
    printf "yes\n"
    android_target=y
    lang_flags="$lang_flags -U__ANDROID_API__ -D__ANDROID_API__=65535 -D_BSD_SOURCE"
    printf "Regenerating config.make ..."
    gen_config_make
    printf "done\n"
  else
    printf "no\n"
  fi
fi

#
# Detect stupid FreeBSD problem: no defined way to reveal
# traditional BSD functions if Unix compliance is selected with
# _XOPEN_SOURCE. Heaven help these troglodytes.
#

printf "Detecting what symbol reveals BSD functions ... "

cat > conftest.c <<!
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
  int (*pdaemon)(int, int) = &daemon;
}
!

if conftest ; then
  printf "none needed\n"
else
  for flag in _DEFAULT_SOURCE _BSD_SOURCE __BSD_VISIBLE _GNU_SOURCE _X_OOPS; do
    if [ $flag = _X_OOPS ] ; then
      printf "failed\n"
      break
    fi
    
    if conftest EXTRA_FLAGS=-D$flag ; then
      printf "%s\n" $flag 
      lang_flags="$lang_flags -D$flag"
      gen_config_make
      break
    fi
  done
fi


if [ $do_nopie ] ; then
  printf "Checking how to disable PIE ..."
  nopie_flags=

  for flag in -nopie -no-pie ; do
    if conftest EXTRA_FLAGS=$flag && ! grep -q option conftest.err ; then
      nopie_flags=" $flag"
      break
    fi
  done

  for flag in -fnopie -fno-pie ; do
    if conftest EXTRA_FLAGS="$flag$nopie_flags" && ! grep -q option conftest.err ; then
      nopie_flags="$nopie_flags $flag"
      break
    fi
  done

  if [ -n "$nopie_flags" ]; then
    printf "%s\n" "$nopie_flags"
    opt_flags="$opt_flags$nopie_flags"
  else
    printf " n/a\n"
  fi
fi

#
# Check for annoying warnings from ctype.h macros
#

printf "Checking for annoying warnings from <ctype.h> macros ... "

cat > conftest.c <<!
#include <ctype.h>

int main(void)
{
  char x = '3';
  return isdigit(x);
}
!
if conftest EXTRA_FLAGS=-Werror ; then
  printf "absent\n"
else
  printf "present\n"
  cat >> config.h <<!
$(for x in isalpha isupper islower isdigit isxdigit isalnum isspace \
           ispunct isprint isgraph iscntrl isblank ; do \
    printf "#undef %s\n" $x ; done)
!
fi

#
# Check what kind of C type we have for integers wider than long,
# if any.
#
printf "Checking what C type we have for integers wider than \"long\" ... "

longlong=

for try_type in int64 __int64 "long long" ; do
  cat > conftest.c <<!
$try_type value;
!
  if conftest_o ; then
    longlong=$try_type
    break
  fi
done

if [ -n "$longlong" ] ; then
  printf '"%s"\n' "$longlong"
  printf "#define HAVE_LONGLONG_T 1\n" >> config.h
  printf "#define LONGLONG_TYPE \"%s\"\n" "$longlong" >> config.h
  printf "typedef $longlong longlong_t;\n" >> config.h
else
  printf "none\n"
fi

printf "Checking what C type we have for unsigned integers wider than \"long\" ... "

ulonglong=

for try_type in uint64 __uint64 "unsigned long long" ; do
  cat > conftest.c <<!
$try_type value;
!
  if conftest_o; then
    ulonglong=$try_type
    break
  fi
done

if [ -n "$ulonglong" ] ; then
  printf '"%s"\n' "$ulonglong"
  printf "#define HAVE_ULONGLONG_T 1\n" >> config.h
  printf "typedef $ulonglong ulonglong_t;\n" >> config.h
else
  printf "none\n"
fi

printf "Checking what C type we have for integers wider than \"long long\" ... "

superlong=

if [ -z "$broken128" ] ; then
  for try_type in int128 int128_t __int128 __int128_t ; do
    cat > conftest.c <<!
#include "config.h"
int main(void)
{
   extern longlong_t a, b;
   $try_type value = ($try_type) a * ($try_type) b;
   return 0;
}
longlong_t a, b;
!
    if conftest_o ; then
      superlong=$try_type
      break
    fi
  done
fi

if [ -n "$superlong" ] ; then
  printf '"%s"\n' "$superlong"
else
  printf "none\n"
fi

printf "Checking what C type we have for u. integers wider than \"long long\" ... "

superulong=

if [ -z "$broken128" ] ; then
  for try_type in uint128 uint128_t __uint128 __uint128_t 'unsigned int128'; do
    cat > conftest.c <<!
#include "config.h"
int main(void)
{
   extern longlong_t a, b;
   $try_type value = ($try_type) a * ($try_type) b;
   return 0;
}
longlong_t a, b;
!
    if conftest_o ; then
      superulong=$try_type
      break
    fi
  done
fi

if [ -n "$superulong" ] ; then
  printf '"%s"\n' "$superulong"
else
  printf "none\n"
fi

if [ -n "$superlong" -a -n "$superulong" ] ; then
  printf "#define HAVE_SUPERLONG_T 1\n" >> config.h
  printf "typedef $superlong superlong_t;\n" >> config.h
  printf "typedef $superulong superulong_t;\n" >> config.h
fi

printf "Checking what C integer type can hold a pointer ... "

if [ -z "$intptr" ] ; then
  cat > conftest.c <<!
#include <stddef.h>
#include <limits.h>
#include "config.h"

#define D(N, Z) ((N) ? (N) + '0' : Z)
#define UD(S) D((S) / 10, ' ')
#define LD(S) D((S) % 10, '0')
#define DEC(S) { UD(S), LD(S) }

struct sizes {
  char h_BYTE[32], s_BYTE[2];
#if HAVE_SUPERLONG_T
  char h_SUPERLONG[32], s_SUPERLONG[2];
#endif
#if HAVE_LONGLONG_T
  char h_LONGLONG[32], s_LONGLONG[2];
#endif
  char h_PTR[32], s_PTR[2];
  char h_LONG[32], s_LONG[2];
  char h_INT[32], s_INT[2];
  char h_SHORT[32], s_SHORT[2];
  char h_WCHAR[32], s_WCHAR[2];
  char nl[2];
} foo = {
  "\nSIZEOF_BYTE=", DEC(CHAR_BIT),
#if HAVE_SUPERLONG_T
  "\nSIZEOF_SUPERLONG_T=", DEC(sizeof (superlong_t)),
#endif
#if HAVE_LONGLONG_T
  "\nSIZEOF_LONGLONG_T=", DEC(sizeof (longlong_t)),
#endif
  "\nSIZEOF_PTR=", DEC(sizeof (char *)),
  "\nSIZEOF_LONG=", DEC(sizeof (long)),
  "\nSIZEOF_INT=", DEC(sizeof (int)),
  "\nSIZEOF_SHORT=", DEC(sizeof (short)),
  "\nSIZEOF_WCHAR_T=", DEC(sizeof (wchar_t)),
  "\n"
};
!

  if ! conftest_o ; then
    printf "failed\n\n"

    printf "Errors from compilation: \n\n"
    cat conftest.err
    exit 1
  fi

  eval $(tr '\0' ' ' < conftest.o  | grep SIZEOF | sed -e 's/  *//')

  tr '\0' ' ' < conftest.o  | grep SIZEOF | sed -e 's/=  */ /' -e 's/^/#define /' >> config.h

  if [ $SIZEOF_PTR -eq 0 -o $SIZEOF_BYTE -eq 0 ] ; then
    printf "failed\n"
    exit 1
  fi

  if [ $SIZEOF_PTR -eq $SIZEOF_SHORT ] ; then
    intptr="short"
  elif [ $SIZEOF_PTR -eq $SIZEOF_INT ] ; then
    intptr="int"
  elif [ $SIZEOF_PTR -eq $SIZEOF_LONG ] ; then
    intptr="long"
  elif [ $SIZEOF_PTR -eq $SIZEOF_LONGLONG_T ] ; then
    intptr="longlong_t"
  fi

  if [ -z "$intptr" ] ; then
    printf "failed\n"
    exit 1
  fi
fi

printf '"%s"\n' "$intptr"
printf "typedef $intptr int_ptr_t;\n" >> config.h
printf "typedef unsigned $intptr uint_ptr_t;\n" >> config.h
printf "#define INTPTR_TYPE \"%s\"\n" "$intptr" >> config.h
intptr_max_expr="((((convert(int_ptr_t, 1) << $((SIZEOF_PTR * SIZEOF_BYTE - 2))) - 1) << 1) + 1)"
printf "#define INT_PTR_MAX %s\n" "$intptr_max_expr" >> config.h
printf "#define INT_PTR_MIN (-INT_PTR_MAX-1)\n" >> config.h
printf "#define UINT_PTR_MAX (convert(uint_ptr_t, -1))\n" >> config.h
double_intptr_max_expr="((((convert(double_intptr_t, 1) << $((2 * SIZEOF_PTR * SIZEOF_BYTE - 2))) - 1) << 1) + 1)"
printf "#define SIZEOF_DOUBLE_INTPTR (2*SIZEOF_PTR)\n" >> config.h
printf "#define DOUBLE_INTPTR_MAX %s\n" "$double_intptr_max_expr" >> config.h
printf "#define DOUBLE_INTPTR_MIN (-DOUBLE_INTPTR_MAX-1)\n" >> config.h
printf "#define DOUBLE_UINTPTR_MAX (convert(double_uintptr_t, -1))\n" >> config.h

if [ -n "$longlong" ] && [ $SIZEOF_LONGLONG_T -eq $(( 2 * SIZEOF_PTR )) ]
then
  printf "#define HAVE_DOUBLE_INTPTR_T 1\n" >> config.h
  printf "typedef longlong_t double_intptr_t;\n" >> config.h
  printf "typedef ulonglong_t double_uintptr_t;\n" >> config.h
elif [ -n "$superlong" ] && [ $SIZEOF_SUPERLONG_T -eq $(( 2 * SIZEOF_PTR )) ]
then
  printf "#define HAVE_DOUBLE_INTPTR_T 1\n" >> config.h
  printf "typedef superlong_t double_intptr_t;\n" >> config.h
  printf "typedef superulong_t double_uintptr_t;\n" >> config.h
fi

#
# Endianness.
#

printf "Checking target machine endianness ... "
cat > conftest.c <<!
#define USPELL(C0, C1, C2, C3) \
  ((unsigned) C0 << 24 | \
   (unsigned) C1 << 16 | \
   (unsigned) C2 << 8 | (unsigned) C3)

unsigned x[6] = {
  0,
  USPELL('L', 'I', 'S', 'P'),
  USPELL('U', 'N', 'I', 'X'),
  USPELL('C', 'O', 'R', 'E'),
  USPELL('D', 'W', 'I', 'M'),
  0
};
!

if ! conftest_o ; then
  printf "failed\n";
  exit 1;
else
  if grep -q 'PSILXINUEROCMIWD' conftest.o ; then
    printf "little\n";
    printf "#define HAVE_LITTLE_ENDIAN 1\n" >> config.h
  elif grep -q 'LISPUNIXCOREDWIM' conftest.o ; then
    printf "big\n";
    printf "#define HAVE_LITTLE_ENDIAN 0\n" >> config.h
  else
    printf "failed\n"
    exit 1
  fi
fi

#
# Inline functions
# 

printf "Checking how to declare inline functions ... "

if [ -z "$inline" ] ; then
  for inline in \
    "${cplusplus:+inline}" "static inline" \
    "static __inline__" "static"
  do
    cat > conftest1.c <<!
$inline int func(void)
{
  return 0;
}

int main(void)
{
  return func();
}
!
    cat > conftest2.c <<!
$inline int func(void)
{
  return 0;
}
!
    rm -f conftest2$exe
    if ! $make conftest2 > conftest.err 2>&1 || ! [ -x conftest2 ] ; then
      continue
    fi
    break
  done
fi

printf '"%s"\n' "$inline"
printf "#define INLINE $inline\n" >> config.h

#
# DBL_DECIMAL_DIG
#

printf "Checking for DBL_DECIMAL_DIG ... "

for try_sym in DBL_DECIMAL_DIG __DBL_DECIMAL_DIG__ ; do
  cat > conftest.c <<!
#include <float.h>

#ifndef $try_sym
#error $try_sym not defined
#else
int main(void)
{
  return 0;
}
#endif
!
  if conftest ; then
    printf "yes (%s)\n" $try_sym
    printf "#define FLO_MAX_DIG $try_sym\n" >> config.h
    have_dbl_decimal_dig=y
    break
  fi
done

if ! [ $have_dbl_decimal_dig ] ; then
    printf "no\n"
    printf "#define FLO_MAX_DIG (DBL_DIG + 2)\n" >> config.h
fi

#
# Rounding mode control.
#

printf "Checking for fesetround and fegetround ... "

cat > conftest.c <<!
#include <fenv.h>

int main(void)
{
  int mode = fegetround();
  fesetround(FE_TONEAREST);
  fesetround(FE_DOWNWARD);
  fesetround(FE_UPWARD);
  fesetround(FE_TOWARDZERO);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_ROUNDING_CTL_H 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for fpclassify ..."

cat > conftest.c <<!
#include <math.h>

int main(void)
{
  double x = 3.14;
  switch (fpclassify(x)) {
  case FP_ZERO:
  case FP_NORMAL:
  case FP_SUBNORMAL:
  case FP_INFINITE:
  case FP_NAN:
  default:
    break;
  }
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_FPCLASSIFY 1\n" >> config.h
else
  printf "no\n"
fi

#
# Valgrind
#

if [ -n "$valgrind" ] ; then
  printf "Checking valgrind API availability ... "

  cat > conftest.c <<!
#include <valgrind/memcheck.h>

#ifdef VALGRIND_DO_CLIENT_REQUEST

int main(void)
{
  return 0;
}

#else
syntax error
#endif
!
  if ! conftest ; then
    printf "failed\n\n"
    printf "Errors from compilation: \n\n"
    cat conftest.err
    exit 1
  fi

  printf "okay\n"
  printf "#define HAVE_VALGRIND 1\n" >> config.h
fi

#
# Lex and Yacc tests
#

if [ $maintainer ] ; then
  printf "Checking for lex ... "

  if [ -z "$lex_given" -a -z "$lexname_given" ] ; then
    for lexname in '$(LEX)' "lex" "flex" "" ; do
      rm -f lex.yy.c
      if $make lexname="$lexname" lex.yy.c > /dev/null 2>&1; then
        break;
      fi
    done
    if [ -z "$lexname" ] ; then
      printf "not found\n"
      exit 1
    fi
  else
    rm -f lex.yy.c
    if ! $make lexname="$lexname" lex.yy.c > /dev/null 2>&1; then
      printf "error\n\n"
      printf 'values --lexname="%s" --lex="%s" are not working\n\n' "$lexname" "$lex"
      printf 'A GNU Flex compatible lex is required\n\n'
      exit 1
    fi
  fi

  rm -f lex.yy.c

  printf '"%s"\n' "$lexname"

  printf "Checking for yacc program ... "

  if [ -z "$yacc_given" -a -z "$yaccname_given" ] ; then
    for yaccname in '$(YACC)' "yacc" "byacc" "bison -y" "" ; do
      yaccpath=$($make yaccname="$yaccname" conftest.yacc)
      if command -v $yaccpath > /dev/null ; then
        break;
      fi
    done

    if [ -z "$yaccname" ] ; then
      printf "not found\n"
      exit 1
    fi

    printf '"%s" (path "%s")\n' "$yaccname" "$yaccpath"
  else
    yaccpath=$($make conftest.yacc)
    case $yaccpath in
    *bison )
      printf "error\n\n"
      printf "GNU Bison needs -y to behave like yacc\n\n"
      printf "This needs to be specified in the --yaccname or --yacc option\n\n"
      exit 1
      ;;
    * )
      if ! command -v $yaccpath > /dev/null ; then
        printf "not found\n\n"
        exit 1
      fi
      printf "given\n"
      ;;
    esac
  fi

  printf "Checking if yacc program is GNU Bison ... "

  gen_config_make

  bison_version="$($make conftest.yacc-version | grep -E '[Bb]ison')" || true

  if [ -n "$bison_version" ] ; then
    set -- $bison_version
    printf "yes (%s)\n" "$4"
    save_ifs=$IFS ; IFS=. ; set -- $4 ; IFS=$save_ifs
    if [ "$1.$2" != "2.5" ] ; then
      echo "GNU Bison 2.5 is required"
      exit 1
    fi
  else
    printf "no\n"
  fi
fi

#
# Check for parallel build
#
if [ $maintainer ] && ! [ $parallelmake_given ] ; then
  parallelmake=y
fi

#
# sys/wait.h
#

printf "Checking whether we have <sys/wait.h> ... "

cat > conftest.c <<!
#include <sys/wait.h>

int main(void)
{
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_SYS_WAIT 1\n" >> config.h
else
  printf "no\n"
fi

#
# sys/stat.h
#

printf "Checking whether we have <sys/stat.h> ... "

cat > conftest.c <<!
#include <sys/stat.h>

struct stat s;

int main(void)
{
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_SYS_STAT 1\n" >> config.h
  have_sys_stat=y
else
  printf "no\n"
fi

if [ "$have_sys_stat" ] ; then
  printf "Checking for sub-second resolution time in struct stat ... "

  cat > conftest.c <<!

#include <sys/stat.h>

struct stat s;

int main(void)
{
  return s.st_mtim.tv_nsec != 0;
}
!
  if conftest ; then
    printf "yes\n"
    printf "#define HAVE_STAT_NSEC 1\n" >> config.h
  else
    printf "no\n"
  fi
fi

#
# utime, utimes, utimensat and futimens
#

printf "Checking for utime ... "

cat > conftest.c <<!
#include <utime.h>

int main(void)
{
  struct utimbuf utb;
  int res = utime("path", &utb);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_UTIME 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for utimes ... "

cat > conftest.c <<!
#include <sys/time.h>

int main(void)
{
  struct timeval tv[2];
  int res = utimes("path", tv);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_UTIMES 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for futimes ... "

cat > conftest.c <<!
#include <sys/time.h>

int main(void)
{
  struct timeval tv[2];
  int res = futimes(42, tv);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_FUTIMES 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for lutimes ... "

cat > conftest.c <<!
#include <sys/time.h>

int main(void)
{
  struct timeval tv[2];
  int res = lutimes("path", tv);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_LUTIMES 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for utimensat and futimens ... "

cat > conftest.c <<!
#include <sys/stat.h>
#include <fcntl.h>

int main(void)
{
  struct timespec ts[2];
  int resu = utimensat(AT_FDCWD, "path", ts, AT_SYMLINK_NOFOLLOW);
  int resf = futimens(0, ts);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_FUTIMENS 1\n" >> config.h
else
  printf "no\n"
fi

printf "#define HAVE_FILE_STAMP_CHANGE " >> config.h
printf "(HAVE_UTIMES || HAVE_FUTIMES || HAVE_FUTIMENS)\n" >> config.h
#
# environ
#

printf "Checking whether we have environ ... "

cat > conftest.c <<!
#include <stdio.h>

int main(void)
{
  extern char **environ;
  puts(environ[0]);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_ENVIRON 1\n" >> config.h
else
  printf "no\n"
fi

#
# GetEnvironmentStrings
#

printf "Checking whether we have GetEnvironmentStrings ... "

cat > conftest.c <<!
#include <windows.h>

int main(void)
{
  WCHAR *ptr = GetEnvironmentStringsW();
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_GETENVIRONMENTSTRINGS 1\n" >> config.h
  have_windows_h=y
else
  printf "no\n"
fi

#
# fork, pipe, exec, waitpid.
#

printf "Checking for POSIX fork/pipe/exec/waitpid ... "

cat > conftest.c <<!
#include "config.h"
#if HAVE_SYS_WAIT
#include <sys/wait.h>
#endif
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char **argv)
{
  int status, fd[2];
  pid_t p = fork();
  int res = pipe(fd);
  (void) execvp(argv[0], argv);
  (void) waitpid(p, &status, 0);
  (void) res;
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_FORK_STUFF 1\n" >> config.h
  have_unistd=y
  have_sys_types=y
else
  printf "no\n"
fi

printf "Checking for POSIX getppid ... "

cat > conftest.c <<!
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char **argv)
{
  pid_t p = getppid();
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_GETPPID 1\n" >> config.h
  have_unistd=y
  have_sys_types=y
else
  printf "no\n"
fi

#
# errno stuff
#

printf "Checking for strerror_r ..."

for type in int 'char *' ; do
  cat > conftest.c <<!
#include <string.h>

int main(int argc, char **argv)
{
  $type (*fp)(int, char *, size_t) = strerror_r;
  return 0;
}
!
  if conftest EXTRA_FLAGS=-Werror=incompatible-pointer-types ; then
    if [ "$type" = int ] ; then
      printf "yes (POSIX)\n"
      printf "#define HAVE_STRERROR_POSIX 1\n" >> config.h
    else
      printf "yes (GNU)\n"
      printf "#define HAVE_STRERROR_GNU 1\n" >> config.h
    fi
    have_strerror_r=y
    break
  fi
done

[ $have_strerror_r ] || printf "no\n"

#
# fcntl
#

printf "Checking for POSIX fcntl ... "

cat > conftest.c <<!
#include "config.h"
#include <fcntl.h>

int main(int argc, char **argv)
{
  int err = fcntl(0, F_SETFD, FD_CLOEXEC);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_FCNTL 1\n" >> config.h
else
  printf "no\n"
fi

#
# poll
#

printf "Checking for poll ... "

cat > conftest.c <<!
#include <poll.h>
#include "config.h"

int main(int argc, char **argv)
{
  static struct pollfd fds[42];
  nfds_t n = 42;
  int err = poll(fds, 42, 1000);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_POLL 1\n" >> config.h
else
  printf "no\n"
fi

#
# Check for fields inside struct tm
#

printf "detecting timezone fields in struct tm ... "

for try_field in tm_gmtoff __tm_gmtoff ; do
  cat > conftest.c <<!
#include <time.h>
int x = sizeof ((struct tm *) 0)->$try_field;
!
  if conftest_o ; then
    printf "#define HAVE_TM_GMTOFF 1\n" >> config.h
    printf "#define TM_GMTOFF %s\n" $try_field >> config.h
    break
  fi
done

for try_field in tm_zone __tm_zone ; do
  cat > conftest.c <<!
#include <time.h>
int x = sizeof ((struct tm *) 0)->$try_field;
!
  if conftest_o ; then
    printf "#define HAVE_TM_ZONE 1\n" >> config.h
    printf "#define TM_ZONE %s\n" $try_field >> config.h
    break
  fi
done

printf "done\n"

printf "Checking for timegm function ... "

cat > conftest.c <<!
#include <time.h>

int main(void)
{
  time_t (*ptgm)(struct tm *) = &timegm;
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_TIMEGM 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for setenv and unsetenv functions ... "

cat > conftest.c <<!
#include <stdlib.h>

int main(void)
{
  setenv("TERM", "foo", 1);
  unsetenv("TERM");
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_SETENV 1\n" >> config.h
else
  printf "no\n"
fi
printf "Checking for tzset function ... "

cat > conftest.c <<!
#include <time.h>

int main(void)
{
  tzset();
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_TZSET 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for localtime_r and gmtime_r functions ... "

cat > conftest.c <<!
#include <time.h>

int main(int argc, char **argv)
{
  struct tm stm;
  time_t t;

  localtime_r(&t, &stm);
  gmtime_r(&t, &stm);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_GMTIME_R 1\n" >> config.h
  have_unistd=y
else
  printf "no\n"
fi

printf "Checking for strptime function ... "

cat > conftest.c <<!
#include <time.h>

int main(int argc, char **argv)
{
  struct tm stm = { 0 };
  strptime("2016-08-20 00:00:00", "%Y-%m-%d %H:%M:%S", &stm);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_STRPTIME 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for POSIX sleep function ... "

cat > conftest.c <<!
#include <unistd.h>

int main(int argc, char **argv)
{
  sleep(42);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_POSIX_SLEEP 1\n" >> config.h
  have_unistd=y
else
  printf "no\n"
fi

printf "Checking for POSIX usleep function ... "

cat > conftest.c <<!
#include <unistd.h>

int main(int argc, char **argv)
{
  usleep(42);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_POSIX_USLEEP 1\n" >> config.h
  have_unistd=y
else
  printf "no\n"
fi

printf "Checking for POSIX nanosleep function ... "

cat > conftest.c <<!
#include <time.h>

int main(int argc, char **argv)
{
  struct timespec ts;
  nanosleep(&ts, &ts);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_POSIX_NANOSLEEP 1\n" >> config.h
  have_unistd=y
else
  printf "no\n"
fi

printf "Checking for BSD daemon function ... "

cat > conftest.c <<!
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv)
{
  int (*pdaemon)(int, int) = &daemon;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_DAEMON 1\n" >> config.h
  have_unistd=y
else
  printf "no\n"
fi

printf "Checking for isatty function ... "

cat > conftest.c <<!
#include <unistd.h>

int main(void)
{
  isatty(0);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_ISATTY 1\n" >> config.h
  have_unistd=y
else
  printf "no\n"
fi

printf "Checking for syslog ... "

cat > conftest.c <<!
#include <syslog.h>

int main(void)
{
  openlog("foo", LOG_CONS, LOG_DAEMON);
  syslog(LOG_EMERG, "bar %d\n", 3);
  setlogmask(0);
  closelog();
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_SYSLOG 1\n" >> config.h
  have_syslog=y
else
  printf "no\n"
fi

printf "Checking for reasonably modern POSIX signal handling ... "

cat > conftest.c <<!
#include <signal.h>
#include <setjmp.h>

int main(void)
{
  sigjmp_buf jb;
  static struct sigaction olda, newa;
  static sigset_t olds, news;
  sigaction(0, &newa, &olda);
  sigprocmask(SIG_BLOCK, &news, &olds);
  if (!sigsetjmp(jb, 1)) 
    siglongjmp(jb, 1);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_POSIX_SIGS 1\n" >> config.h
  have_posix_sigs=y
else
  printf "no\n"
fi

printf "Checking for sigaltstack ... "

cat > conftest.c <<!
#include <signal.h>
#include <stdlib.h>

int main(void)
{
  stack_t ss;
  ss.ss_sp = malloc(SIGSTKSZ);
  ss.ss_size = SIGSTKSZ;
  ss.ss_flags = 0;
  return sigaltstack(&ss, 0);
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_SIGALTSTACK 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for strsignal ... "

cat > conftest.c <<!
#include <string.h>
#include <signal.h>

int main(void)
{
  const char *s = strsignal(SIGABRT);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_STRSIGNAL 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for setitimer/getitimer ... "

cat > conftest.c <<!
#include <sys/time.h>

int main(void)
{
  struct itimerval itv, itv2;
  int err;
  err = getitimer(ITIMER_REAL, &itv);
  err = getitimer(ITIMER_VIRTUAL, &itv);
  err = setitimer(ITIMER_VIRTUAL, &itv, &itv2);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_ITIMER 1\n" >> config.h
  have_sys_time=y
else
  printf "no\n"
fi

printf "Checking for makedev ... "

for try_header in sysmacros types ; do
  cat > conftest.c <<!
#include <sys/${try_header}.h>

int main(void)
{
  int d = makedev(1, 2);
  int j = major(d);
  int n = minor(d);
  return 0;
}
!
  if conftest ; then
    printf "yes\n"
    printf "#define HAVE_MAKEDEV 1\n" >> config.h
    case $try_header in
    sysmacros )
      printf "#define HAVE_SYS_SYSMACROS_H 1\n" >> config.h
      ;;
    types )
      have_sys_types=y
      ;;
    esac
    have_makedev=y
    break
  fi
done

if [ -z "$have_makedev" ] ; then
  printf "no\n"
fi

printf "Checking for link, symlink and readlink ... "

cat > conftest.c <<!
#include <unistd.h>

int main(void)
{
  int e1 = symlink("a", "b");
  int e2 = link("c", "d");
  char buf[256];
  ssize_t foo = readlink("e", buf, sizeof buf);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_SYMLINK 1\n" >> config.h
  have_unistd=y
else
  printf "no\n"
fi

printf "Checking for POSIX mkdir ... "

cat > conftest.c <<!
#include "config.h"
#include <sys/stat.h>
#if HAVE_WINDOWS_H
#include <windows.h>
#endif

int main(void)
{
  int e = mkdir("a", 0);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_MKDIR 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for mknod ... "

cat > conftest.c <<!
#include "config.h"
#include <unistd.h>
#if HAVE_SYS_STAT
#include <sys/stat.h>
#endif

int main(void)
{
  int e = mknod("a", 0, 0);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_MKNOD 1\n" >> config.h
  have_unistd=y
else
  printf "no\n"
fi

printf "Checking for mkfifo ... "

cat > conftest.c <<!
#include "config.h"
#if HAVE_SYS_STAT
#include <sys/stat.h>
#endif

int main(void)
{
  int e = mkfifo("a", 0);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_MKFIFO 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for chmod/fchmod ... "
cat > conftest.c <<!
#include <sys/stat.h>

int main(void)
{
  int r0 = chmod("a", S_IWUSR);
  int r1 = fchmod(4, S_IWUSR);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_CHMOD 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for chown/fchown/lchown ... "
cat > conftest.c <<!
#include <unistd.h>

int main(void)
{
  int r0 = chown("a", 0, 0);
  int r1 = fchown(4, 0, 0);
  int r2 = lchown("a", 0, 0);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_CHOWN 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for pipe ... "
cat > conftest.c <<!
#include <unistd.h>

int main(void)
{
  int p[2];
  int r = pipe(p);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_PIPE 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for ftruncate ... "
cat > conftest.c <<!
#include <unistd.h>

int main(void)
{
  int e = ftruncate(0, 42);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_FTRUNCATE 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for _wspawnvp ... "

cat > conftest.c <<!
#include "config.h"
#include <process.h>
#include <wchar.h>

int main(int argc, char **argv)
{
  wchar_t *wargv[] = { L"foo", L"bar", 0 };
  int r = _wspawnvp(_P_WAIT, L"foo", wargv);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_WSPAWN 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for spawnvp ... "

cat > conftest.c <<!
#include "config.h"
#include <process.h>

int main(int argc, char **argv)
{
  int r = spawnvp(_P_WAIT, "foo", argv);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_SPAWN 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for chsize ... "
cat > conftest.c <<!
#include <unistd.h>

int main(void)
{
  int e = chsize(0, 42);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_CHSIZE 1\n" >> config.h
else
  printf "no\n"
fi


printf "Checking for log2 ... "

cat > conftest.c <<!
#include <math.h>

int main(void)
{
  double x = log2(42.0);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_LOG2 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for round ... "
cat > conftest.c <<!
#include <math.h>

int main(void)
{
  double x = round(0.5);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_ROUND 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for hyperbolic functions (sinh, ...) ... "
cat > conftest.c <<!
#include <math.h>

int main(void)
{
  double a = cosh(0.5);
  double b = sinh(0.5);
  double c = tanh(0.5);
  double d = acosh(0.5);
  double e = asinh(0.5);
  double f = atanh(0.5);
  return 0;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_HYPERBOLICS 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for glob ... "

cat > conftest.c <<!
#include <glob.h>

static int errfunc(const char *path, int err)
{
  return 0;
}

int main(void)
{
  glob_t gl;
  int result = glob("*", GLOB_ERR, errfunc, &gl);
  globfree(&gl);
  return result;
}
!
if conftest ; then
  printf "yes\n"
  printf "#define HAVE_GLOB 1\n" >> config.h
  have_glob=y
else
  printf "no\n"
fi

printf "Checking for nftw ... "

cat > conftest.c <<!
#include <ftw.h>
#include <stdlib.h>

static int callback(const char *fpath, const struct stat *sb,
                    int tflag, struct FTW *ftwbuf)
{
   switch (tflag) {
   case FTW_D:
   case FTW_DP:
   case FTW_NS:
   case FTW_SLN:
     break;
   }
   return 0;
}

int main(int argc, char *argv[])
{
   int flags = FTW_DEPTH | FTW_PHYS;
   int res = nftw(argv[1], callback, 20, flags);
   return (res == -1) ? EXIT_FAILURE : 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_FTW 1\n" >> config.h
  have_ftw=y
else
  printf "no\n"
fi

printf "Checking for fnmatch ... "

cat > conftest.c <<!
#include <fnmatch.h>

int main(int argc, char *argv[])
{
  int res = fnmatch("*.txr", "foo.txr", FNM_PATHNAME);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_FNMATCH 1\n" >> config.h
  have_ftw=y
else
  printf "no\n"
fi

printf "Checking for windres ... "

if output=$(windres -V 2> /dev/null) ; then
  printf "yes\n"
  have_windres=y
else
  printf "no\n"
fi

printf "Checking for POSIX geteuid function family ... "

cat > conftest.c <<!
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char **argv)
{
  uid_t u = getuid();
  uid_t e = geteuid();
  gid_t g = getgid();
  gid_t h = getegid();
  setuid(u);
  seteuid(e);
  setgid(g);
  setegid(h);
  getgroups(0, NULL);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_GETEUID 1\n" >> config.h
  have_unistd=y
  have_sys_types=y
else
  printf "no\n"
fi

printf "Checking for {set,get}res{uid,gid} ... "

cat > conftest.c <<!
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char **argv)
{
  uid_t ur, ue, us;
  gid_t gr, ge, gs;
  int gur = getresuid(&ur, &ue, &us);
  int ggr = getresgid(&gr, &ge, &gs);
  int sur = setresuid(0, 0, 0);
  int sgr = setresgid(0, 0, 0);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_SETRESUID 1\n" >> config.h
  have_unistd=y
  have_sys_types=y
else
  printf "no\n"
fi

printf "Checking for setgroups ... "

cat > conftest.c <<!
#include <sys/types.h>
#include <unistd.h>
#include <grp.h>

int main(int argc, char **argv)
{
  int res = setgroups(0, 0);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_SETGROUPS 1\n" >> config.h
  have_unistd=y
elif conftest EXTRA_FLAGS=-D__EXTENSIONS__=1 ; then
  printf "yes\n"
  printf "#define HAVE_SETGROUPS 1\n" >> config.h
  lang_flags="$lang_flags -D__EXTENSIONS__=1" # Solaris buggery
  gen_config_make
  have_unistd=y
  have_sys_types=y
else
  printf "no\n"
fi

printf "Checking for old school getpwent, getpwuid and getpwnam ... "

cat > conftest.c <<!
#include <sys/types.h>
#include <pwd.h>

int main(void)
{
  struct passwd *p = getpwent();
  struct passwd *q = getpwnam("root");
  struct passwd *r = getpwuid(0);
  setpwent();
  endpwent();
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_PWUID 1\n" >> config.h
  have_pwuid=y
  have_sys_types=y
else
  printf "no\n"
fi

if [ "$have_pwuid" ]; then
  printf "Checking for getpwent_r, getpwuid_r, and getpwnam_r ... "

  cat > conftest.c <<!
#include <sys/types.h>
#include <pwd.h>

int main(void)
{
  struct passwd pw;
  struct passwd *p;
  char buf[1024];
  int r0 = getpwent_r(&pw, buf, sizeof buf, &p);
  int r1 = getpwuid_r(0, &pw, buf, sizeof buf, &p);
  int r2 = getpwnam_r("root", &pw, buf, sizeof buf, &p);
  return 0;
}
!

  if conftest ; then
    printf "yes\n"
    printf "#define HAVE_PWUID_R 1\n" >> config.h
  else
    printf "no\n"
  fi
fi

printf "Checking for old school getgrent, getgrgid and getgrnam ... "

cat > conftest.c <<!
#include <sys/types.h>
#include <grp.h>

int main(void)
{
  struct group *g = getgrent();
  struct group *h = getgrnam("root");
  struct group *i = getgrgid(0);
  setgrent();
  endgrent();
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_GRGID 1\n" >> config.h
  have_grgid=y
else
  printf "no\n"
fi

if [ "$have_grgid" ]; then
  printf "Checking for getgrgid_r and getgrnam_r ... "

  cat > conftest.c <<!
#include <sys/types.h>
#include <grp.h>

int main(void)
{
  struct group gr;
  struct group *g;
  char buf[1024];
  int r1 = getgrgid_r(0, &gr, buf, sizeof buf, &g);
  int r2 = getgrnam_r("root", &gr, buf, sizeof buf, &g);
  return 0;
}
!

  if conftest ; then
    printf "yes\n"
    printf "#define HAVE_GRGID_R 1\n" >> config.h
  else
    printf "no\n"
  fi
fi

printf "Checking for crypt ... "

cat > conftest.c <<!
#include <unistd.h>

int main(void)
{
  char *c = crypt("foo", "bar");
  return 0;
}
!

for try_lcrypt in "" "-lcrypt" "no" ; do
  if [ "$try_lcrypt" = "no" ] ; then
    printf "no\n"
    break
  fi
  if conftest EXTRA_LDLIBS=$try_lcrypt; then
    printf "yes\n"
    printf "#define HAVE_CRYPT 1\n" >> config.h
    if [ -n "$try_lcrypt" ] ; then
      conf_ldlibs="${conf_ldlibs:+"$conf_ldlibs "}-lcrypt"
    fi
    break;
  fi
done

printf "Checking for crypt_r ... "

cat > conftest.c <<!
#include <crypt.h>

int main(void)
{
  static struct crypt_data cd;
  char *c = crypt_r("foo", "bar", &cd);
  return 0;
}
!

for try_lcrypt in "" "-lcrypt" "no" ; do
  if [ "$try_lcrypt" = "no" ] ; then
    printf "no\n"
    break
  fi
  if conftest EXTRA_LDLIBS=$try_lcrypt; then
    printf "yes\n"
    printf "#define HAVE_CRYPT_R 1\n" >> config.h
    if [ -n "$try_lcrypt" ] ; then
      conf_ldlibs="${conf_ldlibs:+"$conf_ldlibs "}-lcrypt"
    fi
    break;
  fi
done


printf "Checking for alloca ... "

for try_header in stdlib alloca malloc ; do
  cat > conftest.c <<!
#include <$try_header.h>

int main(int argc, char **argv)
{
  void *bytes = alloca(42);
  return 0;
}
!

  if conftest ; then
    printf "yes\n"
    printf "#define HAVE_ALLOCA_%s 1\n" $try_header >> config.h
    have_alloca=y
    break;
  fi
done

if [ -z "$have_alloca" ] ; then
  printf "no\n"
  printf "TXR requires the alloca function.\n"
  exit 1
fi

printf "Checking for malloc-with-alignment function ... "

while true ; do
  cat > conftest.c <<!
#include <stdlib.h>

int main(void)
{
  void *bytes = memalign(16, 42);
  return 0;
}
!

  if conftest ; then
    printf "memalign\n"
    printf "#define HAVE_MEMALIGN 1\n" $try_header >> config.h
    break;
  fi

  cat > conftest.c <<!
#include <malloc.h>

int main(void)
{
  void *bytes = memalign(16, 42);
  return 0;
}
!

  if conftest ; then
    printf "memalign\n"
    printf "#define HAVE_MEMALIGN 1\n" $try_header >> config.h
    printf "#define HAVE_MALLOC_H 1\n" $try_header >> config.h
    break;
  fi

  cat > conftest.c <<!
#include <stdlib.h>

int main(void)
{
  void *bytes;
  int res = posix_memalign(&bytes, 16, 42);
  return 0;
}
!
  if conftest ; then
    printf "posix_memalign\n"
    printf "#define HAVE_POSIX_MEMALIGN 1\n" $try_header >> config.h
    break;
  fi

  printf "none\n"
  break
done

printf "Checking for termios ... "

cat > conftest.c <<!
#include <termios.h>

int main(int argc, char **argv)
{
  struct termios t;
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_TERMIOS 1\n" >> config.h
  have_termios=y
else
  printf "no\n"
fi

printf "Checking for struct winsize ... "

for termios_define in NOTHING __EXTENSIONS__ ; do
  cat > conftest.c <<!
#define $termios_define
#include <sys/ioctl.h>
#include <termios.h>

int main(int argc, char **argv)
{
  struct winsize ws;
  return 0;
}
!
  if conftest ; then
    printf "yes\n"
    printf "#define HAVE_WINSIZE 1\n" >> config.h
    have_winsize=y
    break;
  fi
done

if [ -z "$have_winsize" ] ; then
  printf "no\n"
fi

printf "Checking for mkstemp ... "

cat > conftest.c <<!
#include <stdlib.h>

int main(int argc, char **argv)
{
  char templ[] = "abcXXXXXX";
  int fd = mkstemp(templ);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_MKSTEMP 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for mkdtemp ... "

cat > conftest.c <<!
#include <stdlib.h>

int main(int argc, char **argv)
{
  char templ[] = "abcXXXXXX";
  char *s = mkdtemp(templ);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_MKDTEMP 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for mkstemps ... "

cat > conftest.c <<!
#include <stdlib.h>

int main(int argc, char **argv)
{
  char templ[] = "abcXXXXXX.xyz";
  int fd = mkstemps(templ, 4);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_MKSTEMPS 1\n" >> config.h
else
  printf "no\n"
fi

#
# Low stack size on Windows fails the man or boy test case.
#

printf "Do we need to set stack size ... "

if uname -a | grep -q -E 'MINGW|CYGWIN' ; then
  conf_ldflags="-Wl,--stack,16777216${conf_ldflags:+" $conf_ldflags"}"
  printf "yes\n"
else
  printf "no\n"
fi

#
# Do we have fseeko and ftello?
#

printf "Checking for fseeko and ftello ... "

cat > conftest.c <<!
#include <stdio.h>
#include <sys/types.h>

int main(int argc, char **argv)
{
  int res = fseeko(stdin, 0, SEEK_CUR);
  off_t pos = ftello(stdin);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_FSEEKO 1\n" >> config.h
  have_sys_types=y
elif conftest EXTRA_FLAGS=-D_LARGEFILE_SOURCE ; then
  printf "yes\n"
  printf "#define HAVE_FSEEKO 1\n" >> config.h
  lang_flags="$lang_flags -D_LARGEFILE_SOURCE"
  have_sys_types=y
else
  printf "no\n"
fi

printf "Checking how to enable 64 bit file offsets ... "

file_offset_define=none

for try in NOTHING _LARGE_FILES=1 _FILE_OFFSET_BITS=64 ; do
  cat > conftest.c <<!
#include <limits.h>
#include <sys/types.h>

#define D(N, Z) ((N) ? (N) + '0' : Z)
#define UD(S) D((S) / 10, ' ')
#define LD(S) D((S) % 10, '0')
#define DEC(S) { UD(S), LD(S) }

struct sizes {
  char h_BYTE[32], s_BYTE[2];
  char h_OFF_T[32], s_OFF_T[2];
  char nl[2];
} foo = {
  "\nSIZEOF_BYTE=", DEC(CHAR_BIT),
  "\nSIZEOF_OFF_T=", DEC(sizeof (off_t)),
  "\n"
};

!
  if ! conftest_o ; then
    printf "failed\n\n"

    printf "Errors from compilation: \n\n"
    cat conftest.err
    exit 1
  fi

  eval $(tr '\0' ' ' < conftest.o  | grep SIZEOF | sed -e 's/  *//')

  tr '\0' ' ' < conftest.o  | grep SIZEOF | sed -e 's/=  */ /' -e 's/^/#define /' >> config.h

  if [ $SIZEOF_OFF_T -eq 0 -o $SIZEOF_BYTE -eq 0 ] ; then
    printf "failed\n"
    exit 1
  fi

  if [ $(( SIZEOF_BYTE * SIZEOF_OFF_T )) -eq 64 ] ; then
    if [ $try = NOTHING ] ; then
      printf "default\n"
      file_offset_define=
    else
      printf -- "-D%s\n" $try
      file_offset_define=$try
    fi
    break;
  fi
done

if [ "$file_offset_define" = none ] ; then
  printf "unable\n"
elif [ -n "$file_offset_define" ] ; then
  lang_flags="$lang_flags -D$file_offset_define"
fi

printf "Checking for socket API ... "

cat > conftest.c <<!
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/un.h>

int main(int argc, char **argv)
{
  static struct sockaddr_in in_addr;
  static struct sockaddr_un un_addr;
  static char buf[256];
  socklen_t len;

  int s = socket(AF_INET, SOCK_STREAM, 0);
  int e0 = bind(s, (struct sockaddr *) &in_addr, sizeof in_addr);
  int e1 = listen(s, 42);
  int e3 = connect(s, (struct sockaddr *) &un_addr, sizeof un_addr);
  int e4 = send(s, buf, sizeof buf, 0);
  int e5 = sendto(s, buf, sizeof buf, 0,
                  (struct sockaddr *) &un_addr, sizeof un_addr);
  int e6 = recv(s, buf, sizeof buf, 0);
  int e7 = (len = sizeof in_addr,
            recvfrom(s, buf, sizeof buf, 0,
                     (struct sockaddr *) &in_addr, &len));
  int e8 = shutdown(s, 0);
  in_addr_t ia = inet_addr("10.0.0.1");

  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_SOCKETS 1\n" >> config.h
  have_sockets=y
  have_sys_types=y
elif conftest EXTRA_LDLIBS="-lsocket -lnsl" ; then
  printf "yes\n"
  printf "#define HAVE_SOCKETS 1\n" >> config.h
  have_sockets=y
  have_sys_types=y
  conf_ldlibs="${conf_ldlibs:+"$conf_ldlibs "}-lsocket -lnsl"
  printf "Need libs for sockets: regenerating config.make ..."
  gen_config_make
  printf "done\n"
else
  printf "no\n"
fi

if [ $have_sockets ] ; then
  printf "Checking for select ... "

  cat > conftest.c <<!
#include <sys/select.h>

int main(int argc, char **argv)
{
  fd_set rfds;
  int res;
  FD_ZERO(&rfds);
  FD_SET(0, &rfds);
  res = res = select(1, &rfds, 0, 0, 0);
  return 0;
}
!
  if conftest; then
    printf "yes\n"
    printf "#define HAVE_SELECT 1\n" >> config.h
  else
    printf "no\n"
  fi
fi

printf "Checking for getaddrinfo ... "

cat > conftest.c <<!
#include <sys/types.h>
#include <netdb.h>
#include <stdio.h>

int main(void)
{
  struct addrinfo hints;
  struct addrinfo *ptr;
  int res = getaddrinfo("node", "serv", &hints, &ptr);
  freeaddrinfo(ptr);
  puts(gai_strerror(res));
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_GETADDRINFO 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for uname ... "

cat > conftest.c <<!
#include <sys/utsname.h>
#include <stdio.h>

int main(void)
{
  struct utsname utn;
  if (uname(&utn) == 0)
    printf("%s:%s:%s:%s:%s\n", utn.sysname,
           utn.nodename, utn.release, utn.version,
           utn.machine);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_UNAME 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for domainname in struct utsname ... "

cat > conftest.c <<!
#include <sys/utsname.h>
#include <stdio.h>

int main(void)
{
  struct utsname utn;
  if (uname(&utn) == 0)
    printf("%s\n", utn.domainname);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_UTSNAME_DOMAINNAME 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for dlopen ... "

cat > conftest.c <<!
#include <dlfcn.h>

int main(void)
{
  void *lib = dlopen("foo.so", 0);
  void *sym = dlsym(lib, "bar");
#if TEST_DLVSYM
  void *vsym = dlvsym(lib, "bar", "1");
#endif
  dlclose(lib);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_DLOPEN 1\n" >> config.h
elif conftest EXTRA_LDLIBS=-ldl ; then
  printf "yes\n"
  printf "#define HAVE_DLOPEN 1\n" >> config.h
  conf_ldlibs="${conf_ldlibs:+"$conf_ldlibs "}-ldl"
else
  printf "no\n"
fi

printf "Checking for dlvsym ... "
if conftest CONF_LDLIBS="$conf_ldlibs" EXTRA_FLAGS=-DTEST_DLVSYM=1 ; then
  printf "yes\n"
  printf "#define HAVE_DLVSYM 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for pkg-config ... "

if pkg-config --version > /dev/null 2>&1 ; then
  printf "present\n"
  have_pkgconfig=y
else
  printf "absent\n"
fi

printf "Checking for libffi ... "

cat > conftest.c <<!
#include <stdio.h>
#include <ffi.h>

int main(void)
{
  ffi_cif cif;
  ffi_type *args[1];
  void *values[1];
  char *s;
  args[0] = &ffi_type_pointer;
  values[0] = &s;
  return ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_sint, args) != FFI_OK;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_LIBFFI 1\n" >> config.h
elif conftest EXTRA_LDLIBS=-lffi ; then
  printf "yes\n"
  printf "#define HAVE_LIBFFI 1\n" >> config.h
  conf_ldlibs="${conf_ldlibs:+"$conf_ldlibs "}-lffi"
elif [ -n "$have_pkgconfig" ] && pkg-config --exists libffi ; then
  libffi_cflags=$(pkg-config --cflags libffi)
  libffi_ldlibs=$(pkg-config --libs-only-l libffi)
  libffi_ldflags=$(pkg-config --libs-only-L libffi)
  if conftest EXTRA_FLAGS="$libffi_cflags" EXTRA_LDFLAGS="$libffi_ldflags" \
              EXTRA_LDLIBS="$libffi_ldlibs"; then
    printf "yes\n"
    printf "#define HAVE_LIBFFI 1\n" >> config.h
    conf_ldlibs="${conf_ldlibs:+"$conf_ldlibs "}$libffi_ldlibs"
    conf_ldflags="${conf_ldflags:+"$conf_ldflags "}$libffi_ldflags"
  else
    printf "no\n"
    libffi_cflags=
  fi
else
  printf "no\n"
fi

printf "Checking for clockid_t ... "
cat > conftest.c <<!
#include <sys/types.h>

int main(void)
{
  clockid_t cid = 0;
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_CLOCKID_T 1\n" >> config.h
  have_sys_types=y
else
  printf "no\n"
fi

printf "Checking for clock_gettime ... "
cat > conftest.c <<!
#include <time.h>

int main(void)
{
  struct timespec ts;
  (void) clock_gettime(CLOCK_REALTIME, &ts);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_CLOCK_GETTIME 1\n" >> config.h
  have_sys_types=y
else
  printf "no\n"
fi

printf "Checking for loff_t ... "
cat > conftest.c <<!
#include <sys/types.h>

int main(void)
{
  loff_t lo = 0;
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_LOFF_T 1\n" >> config.h
  have_sys_types=y
else
  printf "no\n"
fi

printf "Checking for realpath ... "
cat > conftest.c <<!
#include <stdlib.h>

int main(void)
{
  char *rp = realpath("/var/lib", 0);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_REALPATH 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for getexecname ... "
cat > conftest.c <<!
#include <stdlib.h>

int main(void)
{
  const char *rp = getexecname();
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_GETEXECNAME 1\n" >> config.h
else
  printf "no\n"
fi

printf "Checking for getrlimit ... "
cat > conftest.c <<!
#include <sys/resource.h>

int main(void)
{
  struct rlimit rl;
  int res = getrlimit(RLIMIT_STACK, &rl);
  return 0;
}
!

if conftest ; then
  printf "yes\n"
  printf "#define HAVE_RLIMIT 1\n" >> config.h
else
  printf "no\n"
fi

#
# Dependent variables
#

if [ -n "$have_unistd" ] ; then
  printf "#define HAVE_UNISTD_H 1\n" >> config.h
fi

if [ -n "$have_sys_types" ] ; then
  printf "#define HAVE_SYS_TYPES_H 1\n" >> config.h
fi

if [ -n "$have_sys_time" ] ; then
  printf "#define HAVE_SYS_TIME 1\n" >> config.h
fi

if [ -n "$have_windows_h" ] ; then
  printf "#define HAVE_WINDOWS_H 1\n" >> config.h
fi

#
# Extra debugging.
#

if [ -n "$extra_debugging" ] ; then
  printf "Configuring extra debugging, as requested ...\n"
  printf "#define CONFIG_EXTRA_DEBUGGING 1\n" >> config.h
fi

#
# Clean up
#

$make conftest.clean

#
# Some final blurbs into config.h
#

[ -n "$debug_support" ] && printf "#define CONFIG_DEBUG_SUPPORT 1\n" >> config.h
[ -n "$gen_gc" ] && printf "#define CONFIG_GEN_GC 1\n" >> config.h
[ "$small_mem" ] && printf "#define CONFIG_SMALL_MEM 1\n" >> config.h

#
# Regenerate config.make
#

printf "Regenerating config.make ... "
gen_config_make
printf "done\n"

#
# Save configuration in reconfigure
#
cat > reconfigure <<!
#!/bin/sh
#
# Configured on $(date) using these parameters:

$cmdline "\$@"

!
#
# Parting message
#
cat <<!

The configuration seems to have been successful. That doesn't mean it's
correct!  Please check the above output for any problems, and verify that the
contents of the generated files config.make and config.h are sane for the
target platform.

The next step is to build the program with $make.

If that is successful, please follow the INSTALL guide.

Usually, most users just need to "$make tests" and "$make install",
possibly switching to superuser for "$make install" if the prefix
points to a privileged location like /usr/local/.

Also, a script called ./reconfigure has been generated.
This can be used to re-run the configuration with the same parameters.

!