dnl Process this file with autoconf to produce a configure script
dnl ----------------------------------------------------------------------
dnl C++ Class library
dnl (C) 1995 Lassi A. Tuura (<Lassi.Tuura@hut.fi>)
dnl ----------------------------------------------------------------------

AC_REVISION($Revision: 1.2 $)dnl

AC_INIT(src/syserrors.in)
AC_CONFIG_HEADER(SealPlatform/config.h)
AC_CONFIG_AUX_DIR(src)

dnl ----------------------------------------------------------------------
dnl (FIXME!) Configure windows build requirements: W2K or later
dnl Select large file support unconditionally.
AC_DEFINE_UNQUOTED(_WIN32_WINNT, 0x0500)

dnl ----------------------------------------------------------------------
dnl Checks for programs
AC_PROG_CXX
AC_PROG_CXXCPP

dnl ----------------------------------------------------------------------
dnl Check header compatibility.
AC_LANG_C
AC_HEADER_STDC

dnl ----------------------------------------------------------------------
dnl Checks for typedefs, structures, and compiler characteristics
AC_LANG_SAVE
AC_LANG_CPLUSPLUS

dnl ----------------------------------------------------------------------
dnl C++ language stuff
LAT_CHECK_NAMESPACES
LAT_CHECK_NAMESPACE_STD
LAT_CHECK_NAMESPACE_STD_REL_OPS
LAT_CHECK_REL_OPS_IN_STD

LAT_CHECK_PRETTY_FUNCTION
LAT_CHECK_LONG_LONG
LAT_CHECK_INT64
LAT_CHECK_BOOL
LAT_CHECK_EXPLICIT
LAT_CHECK_MUTABLE
LAT_CHECK_RESTRICT
LAT_CHECK_SIGNED
LAT_CHECK_USING
LAT_CHECK_TYPENAME
LAT_CHECK_TYPENAME_IN_BASE
LAT_CHECK_NEW_STYLE_CASTS
LAT_CHECK_DYNAMIC_CAST
LAT_CHECK_TYPEID
LAT_CHECK_FOR_SCOPE
LAT_CHECK_TEMPLATE_INSTANTIATION
LAT_CHECK_TEMPLATE_DEFAULT_ARGS
LAT_CHECK_TEMPLATE_NULL_ARGS
LAT_CHECK_TEMPLATE_NULL_SPEC
LAT_CHECK_TEMPLATE_PARTIAL_SPEC
LAT_CHECK_MEMBER_TEMPLATES
LAT_CHECK_OPERATOR_ARROW
LAT_CHECK_CLASS_ACCESS

LAT_CHECK_STD_NEW_HANDLER
LAT_CHECK_NEW_IOSTREAMS
LAT_CHECK_OSTREAM_CHAR_OVERLOAD
LAT_CHECK_OSTREAM_LONG_DOUBLE_OVERLOAD
LAT_CHECK_OSTREAM_LONG_LONG_OVERLOAD
LAT_CHECK_ITERATOR_TRAITS
LAT_CHECK_ITERATOR
LAT_CHECK_REVERSE_ITERATOR
LAT_CHECK_CXX_STDC_HEADERS

dnl ----------------------------------------------------------------------
dnl General system detection
AC_CHECK_HEADERS(limits.h unistd.h strings.h sys/types.h sys/sysctl.h dnl
		 vm/vm_param.h sys/vmmeter.h crt_externs.h)
AC_LANG_C
AC_CHECK_FUNCS(setenv unsetenv)
AC_LANG_CPLUSPLUS
LAT_CHECK_DECL(strerror, string.h)
LAT_CHECK_UTSNAME_DOMAINNAME
LAT_CHECK_CADDR_T
AC_TYPE_UID_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T

dnl ----------------------------------------------------------------------
dnl Copy limit values from stdint.h.  The limit values are not defined by
dnl default under C++, and we would have to define __STD_LIMIT_MACROS on
dnl command line in order to have them and be protected from different
dnl file inclusion orders: someone could have included stdint.h. before
dnl including any of our headers, rendering any use of __STD_LIMIT_MACROS
dnl ineffective.   Therefore copy the constant values out at configure
dnl time and publish them with our own names.

AC_LANG_C
AC_DEFINE(__STDC_LIMIT_MACROS)
AC_DEFINE(SEAL_PLATFORM_SYSTEM_H)
AC_CHECK_HEADERS(stdint.h)
AC_MSG_CHECKING(limits of integer types)
AC_RUN_IFELSE([AC_LANG_PROGRAM(
  [[#include "SealPlatform/nonstdint.h"
    #include <stdio.h>
    #define STR(x) #x
    #define DUMP(x) fprintf (out, #x " %s\n", STR(x))]],
  [[FILE *out = fopen("conftest.limits", "w");
    #ifdef INT8_MIN
    DUMP(INT8_MIN); DUMP(INT8_MAX); DUMP(UINT8_MAX);
    #endif
    #ifdef INT16_MIN
    DUMP(INT16_MIN); DUMP(INT16_MAX); DUMP(UINT16_MAX);
    #endif
    #ifdef INT32_MIN
    DUMP(INT32_MIN); DUMP(INT32_MAX); DUMP(UINT32_MAX);
    #endif
    #ifdef INT64_MIN
    DUMP(INT64_MIN); DUMP(INT64_MAX); DUMP(UINT64_MAX);
    #endif
    fclose (out);]])],
   [AC_MSG_RESULT(success)
    while read sym value; do
      AC_MSG_CHECKING(value of $sym)
      AC_MSG_RESULT($value)
      AC_DEFINE_UNQUOTED(SEAL_$sym, $value)
    done < conftest.limits
    : rm conftest.limits],
   [AC_MSG_ERROR(failed)])
AC_LANG_CPLUSPLUS

dnl ----------------------------------------------------------------------
dnl Signals

LAT_CHECK_TYPE_SIGNAL
LAT_CHECK_TYPE_SIGNAL_PROC
LAT_CHECK_POSIX_SIGNALS
LAT_CHECK_POSIX_RT_SIGNALS
LAT_CHECK_SYS_SIGLIST
LAT_CHECK_SIGINFO_SI_UTIME
LAT_CHECK_SIGINFO_SI_INT
LAT_CHECK_SIGINFO_SI_VALUE

LAT_CHECK_DECL(raise, signal.h)
LAT_CHECK_DECL(strsignal, string.h)

dnl ----------------------------------------------------------------------
dnl General I/O

dnl First check for sendfile(), *then* enable large file support
dnl this is because on Linux sendfile() doesn't work on large files,
dnl and the header checks internal feature macros, nothing we can
dnl fiddle.  So this check must come before other file-system stuff.
LAT_CHECK_SENDFILE
AC_DEFINE_UNQUOTED(_FILE_OFFSET_BITS, 64)

dnl Now rest of I/O checking
AC_CHECK_HEADERS(fcntl.h io.h sys/ioctl.h sys/filio.h sys/uio.h)
AC_CHECK_HEADERS(sys/wait.h sys/param.h sys/mman.h)
LAT_CHECK_DECL(pread, unistd.h)
LAT_CHECK_DECL(popen, stdio.h)

dnl ----------------------------------------------------------------------
dnl File system stuff
AC_CHECK_HEADERS(pwd.h)
AC_CHECK_FUNCS(fsync fdatasync)

AC_LANG_C # Solaris CC chokes on the way autoconf checks for this
LAT_CHECK_DECL(getcwd, unistd.h)
LAT_CHECK_DECL(mkstemp, stdlib.h)
LAT_CHECK_DECL(mkdtemp, stdlib.h)
LAT_CHECK_DECL(glob, glob.h)
AC_LANG_CPLUSPLUS

dnl ----------------------------------------------------------------------
dnl Directory iterator; these must be done in C mode
AC_LANG_C
AC_HEADER_DIRENT
AC_FUNC_CLOSEDIR_VOID
AC_LANG_CPLUSPLUS

dnl ----------------------------------------------------------------------
dnl Figure out various i/o selector support things
AC_CHECK_HEADERS(sys/devpoll.h sys/poll.h sys/select.h)
AC_CHECK_FUNCS(kqueue poll)
LAT_FUNC_SELECT_ARG_TYPE
LAT_CHECK_F_SETSIG
LAT_CHECK_F_SETAUXFL


dnl ----------------------------------------------------------------------
dnl Networking
AC_CHECK_HEADERS(sys/sockio.h sys/socket.h sys/un.h netinet/in.h)
AC_CHECK_HEADERS(netdb.h arpa/inet.h)

# FIXME: check/typedef for socklen_t, in_addr_t?
LAT_FUNC_RECV_ARG_TYPE
LAT_FUNC_GETSOCKOPT_LEN_TYPE
LAT_CHECK_SOCKADDR_LENGTH_TYPE
LAT_CHECK_SOCKADDR_UN

AC_CHECK_FUNCS(gethostbyname inet_aton socket)
if test $ac_cv_func_socket = no; then
  # `socket' is not in the default libraries.  Look for it elsewhere.
  for lib in bsd socket inet; do
    AC_CHECK_LIB($lib, socket, [EXTRA="$EXTRA -l$lib"; break])
  done
fi
if test $ac_cv_func_gethostbyname = no; then
  # `gethostname' is not in the default libraries.  Look for it elsewhere.
  for lib in bsd socket inet nsl; do
    AC_CHECK_LIB($lib, gethostbyname, [EXTRA="$EXTRA -l$lib"; break])
  done
fi
if test $ac_cv_func_inet_aton = no; then
  # `inet_aton' is not in the default libraries.  Look for it elsewhere.
  for lib in resolv bsd socket inet nsl; do
    AC_CHECK_LIB($lib, inet_aton,
     [AC_DEFINE(HAVE_INET_ATON)
      EXTRA="$EXTRA -l$lib"; break])
  done
fi

LAT_CHECK_DECL(inet_aton, arpa/inet.h)
LAT_CHECK_DECL(gethostname, unistd.h)

dnl ----------------------------------------------------------------------
dnl Resource information: symbols for program memory layout
for lat_sym in __bss_start __data_start _edata _end _etext \
               _dl_argv __argv __argc; do
  lat_sym_def=`echo $lat_sym | tr "[[a-z]]" "[[A-Z]]" | sed 's/^_*//'`
  AC_MSG_CHECKING(for $lat_sym)
  AC_CACHE_VAL(lat_cv_have_$lat_sym,
    [AC_TRY_LINK([#include <stdio.h>],
	  [extern char $lat_sym[];printf("%x", $lat_sym);],
      [eval lat_cv_have_$lat_sym=yes],
      [eval lat_cv_have_$lat_sym=no])])
  eval lat_result=\$lat_cv_have_$lat_sym
  AC_MSG_RESULT($lat_result)
  if test $lat_result = yes; then
    AC_DEFINE_UNQUOTED(HAVE_SYM_$lat_sym_def)
  fi
done

dnl Resources: program arguments
AC_MSG_CHECKING(for program_invocation_name)
AC_CACHE_VAL(lat_cv_have_program_invocation_name,
 [AC_TRY_LINK([#include <errno.h>
   #include <stdio.h>],[puts(program_invocation_name);],
   lat_cv_have_program_invocation_name=yes,
   lat_cv_have_program_invocation_name=no)])
AC_MSG_RESULT($lat_cv_have_program_invocation_name)
if test "$lat_cv_have_program_invocation_name" = yes; then
  AC_DEFINE(HAVE_PROGRAM_INVOCATION_NAME)
fi

dnl Figure out system information apis
AC_CHECK_HEADERS(sys/times.h sys/resource.h)
AC_LANG_C # Solaris CC chokes on the way autoconf checks for this
AC_CHECK_FUNCS(getpagesize getrusage getrlimit getdtablesize getdtablehi ulimit)
LAT_CHECK_SC_OPEN_MAX
AC_LANG_CPLUSPLUS

dnl ----------------------------------------------------------------------
dnl Time
AC_CHECK_HEADERS(sys/time.h)
AC_CHECK_FUNCS(timegm)
AC_HEADER_TIME
AC_STRUCT_TM
LAT_CHECK_TM_GMTOFF
LAT_CHECK_TM_ZONE
AC_LANG_C
AC_FUNC_UTIME_NULL
AC_LANG_CPLUSPLUS
AC_LANG_C # Solaris CC chokes on the way autoconf checks for this
LAT_CHECK_DECL(strftime, time.h)
AC_LANG_CPLUSPLUS

dnl ----------------------------------------------------------------------
dnl High resolution timers and cycle counters
AC_CHECK_HEADERS(invent.h sys/systemcfg.h sys/processor.h dnl
		 sys/pstat.h machine/inline.h pmapi.h procfs.h dnl
		 mach/mach_time.h)
AC_LANG_C # Solaris CC chokes on the way autoconf checks for this
AC_CHECK_FUNCS(nanosleep usleep times gethrtime clock_gettime)
if test $ac_cv_func_clock_gettime = no; then
   AC_CHECK_LIB(rt, clock_gettime, [EXTRA="$EXTRA -lrt"])
fi
AC_LANG_CPLUSPLUS
for lat_clock in CLOCK_REALTIME CLOCK_MONOTONIC CLOCK_PROCESS_CPUTIME_ID \
		 CLOCK_THREAD_CPUTIME_ID CLOCK_PROFILE CLOCK_PROF \
		 CLOCK_SGI_CYCLE; do
  AC_MSG_CHECKING(for $lat_clock in time.h)
  AC_CACHE_VAL(lat_cv_have_$lat_clock,
    [AC_TRY_COMPILE([#include <time.h>],
      [return $lat_clock;],
      [eval lat_cv_have_$lat_clock=yes],
      [eval lat_cv_have_$lat_clock=no])])
  eval lat_result=\$lat_cv_have_$lat_clock
  AC_MSG_RESULT($lat_result)
  if test $lat_result = yes; then
    AC_DEFINE_UNQUOTED(HAVE_$lat_clock)
  fi
done
AC_CHECK_LIB(pmapi,pm_cycles, [EXTRA="$EXTRA -lpmapi"])
LAT_CHECK_DECL(read_real_time, sys/time.h)
LAT_CHECK_DECL(processor_info, sys/processor.h)
		
AC_MSG_CHECKING(for cpu cycle counter instruction)
lat_ticks_ia32_rdtsc_real='"rdtsc" : "=a" (low), "=d" (high)'
lat_ticks_ia32_rdtsc_rtime='((unsigned long long) low) | ((unsigned long long) high << 32)'
lat_ticks_ia64_ar_itc_real='"mov %0=ar.itc" : "=r" (time)'
# linux and tru64 have virtual counter in the upper bits
lat_ticks_alpha_rpcc_real='"rpcc %0" : "=r" (time)'
lat_ticks_alpha_rpcc_rtime='time & 0xffffffff'
lat_ticks_alpha_rpcc_virt='"rpcc %0" : "=r" (time)'
lat_ticks_alpha_rpcc_vtime='(time + (time << 32)) >> 32'
lat_ticks_parisc_mfctl_real='"mfctl 16,%0" : "=r" (time)'
lat_ticks_mips_mfc0_real='".set push\n\t"
   ".set reorder\n\t"
   "mfc0 %0,$9\n\t"
   ".set pop" : "=r" (time)'
lat_ticks_sparc64_tick_real='"rd %%tick,%0" : "=r" (time)'
AC_CACHE_VAL(lat_cv_ticks_instruction,
  [lat_cv_ticks_instruction=none
   for lat_try in ia32_rdtsc ia64_ar_itc alpha_rpcc parisc_mfctl \
		  mips_mfc0 sparc64_tick; do
     eval "lat_asm=\"\$lat_ticks_${lat_try}_real\""
     AC_TRY_COMPILE([],[unsigned low, high; long long time; __asm__ volatile ($lat_asm)],
       [lat_cv_ticks_instruction=$lat_try; break])
   done])
case $lat_cv_ticks_instruction in
  none ) AC_MSG_RESULT(unknown) ;;
  *    ) lat_nice=`echo $lat_cv_ticks_instruction | sed 's/_/ /'`
         AC_MSG_RESULT($lat_nice)

         eval "lat_asm=\"\$lat_ticks_${lat_cv_ticks_instruction}_real\""
	 eval "lat_time=\"\$lat_ticks_${lat_cv_ticks_instruction}_rtime\""
	 test -z "$lat_time" && lat_time='time'
	 AC_DEFINE_UNQUOTED(CPU_REAL_CYCLES_ASM,$lat_asm)
	 AC_DEFINE_UNQUOTED(CPU_REAL_CYCLES_VALUE,$lat_time)
	 
	 eval "lat_asm=\"\$lat_ticks_${lat_cv_ticks_instruction}_virt\""
	 eval "lat_time=\"\$lat_ticks_${lat_cv_ticks_instruction}_vtime\""
	 if test -n "$lat_asm"; then
	   test -z "$lat_time" && lat_time='time'
	   AC_DEFINE_UNQUOTED(CPU_VIRTUAL_CYCLES_ASM,$lat_asm)
	   AC_DEFINE_UNQUOTED(CPU_VIRTUAL_CYCLES_VALUE,$lat_time)
	 fi
	 ;;
esac

dnl ----------------------------------------------------------------------
dnl Stack tracing and unwinding support
AC_PATH_PROG(PROG_PSTACK, pstack,,$PATH:/usr/proc/bin)
if test -n "$PROG_PSTACK"; then
  AC_DEFINE_UNQUOTED(PROG_PSTACK, "$PROG_PSTACK")
fi
AC_PATH_PROG(PROG_CXXFILT, c++filt)
if test -n "$PROG_CXXFILT"; then
  AC_DEFINE_UNQUOTED(PROG_CXXFILT, "$PROG_CXXFILT")
fi

AC_CHECK_HEADERS(exception.h excpt.h rld_interface.h pdsc.h)

# FIXME: SGI IRIX will require -lexc -ldwarf -lelf!
AC_CHECK_FUNCS(U_STACK_TRACE backtrace_symbols_fd)
AC_CHECK_LIB(xlf90, xl__trbk,
  [EXTRA="$EXTRA -lxlf90";
   AC_DEFINE(HAVE_XL_TRBK)])

dnl ----------------------------------------------------------------------
dnl Figure out dynamic linker capabilities
LAT_CHECK_DECL(dlopen, dlfcn.h)
LAT_CHECK_DECL(dladdr, dlfcn.h)
LAT_CHECK_DECL(shl_load, dl.h)
LAT_CHECK_DECL(load, ldfcn.h)

AC_CHECK_HEADER(loader.h,
 [AC_DEFINE(HAVE_LOADER_H)
  LAT_CHECK_DECL(ldr_next_module, loader.h)])
AC_CHECK_HEADER(link.h,
 [AC_DEFINE(HAVE_LINK_H)

  AC_MSG_CHECKING(_r_debug in link.h)
  AC_CACHE_VAL(lat_cv_have_r_debug,
   [AC_EGREP_CPP(_r_debug,[#include <link.h>],
   lat_cv_have_r_debug=yes,lat_cv_have_r_debug=no)])
  AC_MSG_RESULT($lat_cv_have_r_debug)
  if test "$lat_cv_have_r_debug" = yes; then
    AC_DEFINE(HAVE_R_DEBUG)
  fi

  AC_MSG_CHECKING(l_map_start in link_map)
  AC_CACHE_VAL(lat_cv_have_link_map_l_map_start,
   [AC_TRY_COMPILE([#include <link.h>],[struct link_map p; p.l_map_start;],
     lat_cv_have_link_map_l_map_start=yes,
     lat_cv_have_link_map_l_map_start=no)])
  AC_MSG_RESULT($lat_cv_have_link_map_l_map_start)
  if test "$lat_cv_have_link_map_l_map_start" = yes; then
    AC_DEFINE(HAVE_LINK_MAP_L_MAP_START)
  fi])

AC_CHECK_HEADERS(elf.h sgidefs.h mach-o/dyld.h)
# Disabled: this check succeeds on way too many platforms.
# AC_MSG_CHECKING(for __rld_obj_head)
# AC_CACHE_VAL(lat_cv_have_rld_obj_head,
#  [AC_TRY_LINK([],[extern long *__rld_obj_head; long *p = __rld_obj_head;],
#    lat_cv_have_rld_obj_head=yes,
#   lat_cv_have_rld_obj_head=no)])
# AC_MSG_RESULT($lat_cv_have_rld_obj_head)
# if test "$lat_cv_have_rld_obj_head" = yes; then
#   AC_DEFINE(HAVE_RLD_OBJ_HEAD)
# fi

dnl ----------------------------------------------------------------------
dnl POSIX regexp support
AC_CHECK_HEADERS(regex.h)

dnl ----------------------------------------------------------------------
dnl Figure out system-specific extra libraries we need
AC_SUBST(EXTRA)

dnl ----------------------------------------------------------------------
dnl Set debugging flags
AC_SUBST(NDEBUG)
AC_SUBST(NLOG)
AC_ARG_ENABLE(debugging,[   --disable-debugging            No validation],
 [test "$enableval" = "no" && NDEBUG="-DNDEBUG"])
AC_ARG_ENABLE(logging,  [   --disable-logging              No logging],
 [test "$enableval" = "no" && NLOG="-DNLOG"])

dnl ----------------------------------------------------------------------
dnl Stage out
AC_OUTPUT()
