#!/bin/sh
# Generate config.h from unix.cfg.

trap 'rm -f doit doit.c doit.o doit.log config.out; exit 1' 1 2 3 15

on=
off=
CC=${CC-cc}

# Normally we use VARARGS if __STDC__ is not defined.
# Test whether this assumption is wrong.

cat >doit.c <<\EOF
#ifdef __STDC__
#include <stdarg.h>
int foo(char *s,...)
{
  va_list ap;

  va_start(ap, s);
  va_end(ap);
  return 0;
}
#else
int foo = 0;
#endif
EOF

$CC $CFLAGS -c doit.c >/dev/null 2>&1
if test $? -ne 0
then
	on="$on VARARGS"
fi

cat >doit.c <<\EOF
#include <stddef.h>
int foo = 0;
EOF

if $CC $CFLAGS -c doit.c >/dev/null 2>&1
then
	off="$off STDDEF_H_MISSING"
else
	on="$on STDDEF_H_MISSING"
fi

cat >doit.c <<\EOF
#include <stdlib.h>
int foo = 0;
EOF

if $CC $CFLAGS -c doit.c >/dev/null 2>&1
then
	off="$off STDLIB_H_MISSING"
else
	on="$on STDLIB_H_MISSING"
fi

cat >doit.c <<\EOF
#include <limits.h>
int foo = 0;
EOF

if $CC $CFLAGS -c doit.c >/dev/null 2>&1
then
	off="$off LIMITS_H_MISSING"
else
	on="$on LIMITS_H_MISSING"
fi

cat >doit.c <<\EOF
#include <vfork.h>
int foo = 0;
EOF

if $CC $CFLAGS -c doit.c >/dev/null 2>&1
then
	on="$on HAVE_VFORK_H"
else
	off="$off HAVE_VFORK_H"
fi

cat >doit.c <<\EOF
#include <unistd.h>
int foo = 0;
EOF

if $CC $CFLAGS -c doit.c >/dev/null 2>&1
then
	on="$on HAVE_UNISTD_H"
else
	off="$off HAVE_UNISTD_H"
fi

cat >doit.c <<\EOF
#include <sys/types.h>
#include <sys/stat.h>
int foo = 0;
EOF

if $CC $CFLAGS -c doit.c >/dev/null 2>&1
then
	on="$on HAVE_SYS_STAT_H"
else
	off="$off HAVE_SYS_STAT_H"
fi

cat >doit.c <<\EOF
/* Exit normally unless we need to use isascii. */

#include <ctype.h>
#include <signal.h>

static int whoops()
{
  _exit(1);
}

main()
{
  int c;
#ifdef isascii
#ifdef SIGSEGV
  signal(SIGSEGV, whoops);
#endif
#ifdef SIGBUS
  signal(SIGBUS, whoops);
#endif
#ifdef SIGIOT
  signal(SIGIOT, whoops);
#endif

  for (c = 128; c < 256; c++) {
    if (c == '0' || c == '1' || c == '2' || c == '3' || c == '4' || c == '5'
	|| c == '6' || c == '7' || c == '8' || c == '9') {
      if (!isdigit(c) || isalpha(c) || iscntrl(c) || isspace(c) || ispunct(c))
	exit(1);
    }
    else if (isdigit(c))
      exit(1);
    else if (isalpha(c)) {
      if (iscntrl(c) || isspace(c) || ispunct(c)
	  || (islower(c) && toupper(c) != c && !isupper(toupper(c)))
	  || (isupper(c) && tolower(c) != c && !islower(tolower(c))))
	exit(1);
    }
    else if (islower(c) || isupper(c))
      exit(1);
    else if (iscntrl(c)) {
      if (ispunct(c))
	exit(1);
    }
  }
#endif /* isascii */
  exit(0);
}
EOF

if $CC $CFLAGS -o doit doit.c $LIBS >/dev/null 2>&1 && ./doit 2>/dev/null
then
	# This tries to find the symbol that looks like the array
	# used by <ctype.h>, and sees if its length appears to be 128
	# rather than 256.
	if test 1 = `(nm -n doit 2>/dev/null) | awk '
BEGIN {
	weight["0"] = 0;
	weight["1"] = 1;
	weight["2"] = 2;
	weight["3"] = 3;
	weight["4"] = 4;
	weight["5"] = 5;
	weight["6"] = 6;
	weight["7"] = 7;
	weight["8"] = 8;
	weight["9"] = 9;
	weight["a"] = weight["A"] = 10;
	weight["b"] = weight["B"] = 11;
	weight["c"] = weight["C"] = 12;
	weight["d"] = weight["D"] = 13;
	weight["e"] = weight["E"] = 14;
	weight["f"] = weight["F"] = 15;
}

/^[0-9a-zA-Z]* D .*ctype/ && ctype_nr == 0 {
	ctype_nr = NR;
	addr = 0;
	len = length($1);
	for (i = 1; i <= len; i++)
		addr = addr*16 + weight[substr($1, i, 1)];
}

/^[0-9a-zA-Z]* D / && NR == ctype_nr + 1 {
	next_addr = 0;
	len = length($1);
	for (i = 1; i <= len; i++)
		next_addr = next_addr*16 + weight[substr($1, i, 1)];
}

END {
	size = next_addr - addr;
	if (size >= 128 && size < 256)
		print "1";
	else
		print "0";
}'`
	then
		on="$on USE_ISASCII"
	else
		if ((yes | man 3 ctype) 2>/dev/null) \
		     | sed -e 's/.//g' -e 's/ *$//' -e '/de-$/N' \
                           -e 's/-\n//g' -e '/defined$/N' -e '/only$/N' \
	   		   -e '/where$/N' -e '/isascii$/N' -e '/is$/N' \
			   -e 's/\n/ /g' -e 's/  */ /g' \
		     | grep "defined only where isascii is true" >/dev/null
		then
			on="$on USE_ISASCII"
		else
			off="$off USE_ISASCII"
		fi
	fi
else
	on="$on USE_ISASCII"
fi

cat >doit.c <<\EOF
main(argc, argv)
int argc;
char **argv;
{
  if (argc == 0)
    remove("foo");  
  exit(0);
}
EOF

if $CC $CFLAGS -o doit doit.c $LIBS >/dev/null 2>&1 && ./doit 2>/dev/null
then
	off="$off REMOVE_MISSING"
else
	on="$on REMOVE_MISSING"
fi

cat >doit.c <<\EOF
main(argc, argv)
int argc;
char **argv;
{
  if (argc == 0)
    getopt(argc, argv, "v");  
  exit(0);
}
EOF

if $CC $CFLAGS -o doit doit.c $LIBS >/dev/null 2>&1 && ./doit 2>/dev/null
then
	on="$on HAVE_GETOPT"
else
	off="$off HAVE_GETOPT"
fi

cat >doit.c <<\EOF
main(argc, argv)
int argc;
char **argv;
{
  if (argc == 0)
    access("foo", 4);
  exit(0);
}
EOF

if $CC $CFLAGS -o doit doit.c $LIBS >/dev/null 2>&1 && ./doit 2>/dev/null
then
	on="$on HAVE_ACCESS"
else
	off="$off HAVE_ACCESS"
fi

cat >doit.c <<\EOF
main(argc, argv)
int argc;
char **argv;
{
  if (argc == 0)
    vfork();
  exit(0);
}
EOF

if $CC $CFLAGS -o doit doit.c $LIBS >/dev/null 2>&1 && ./doit 2>/dev/null
then
	on="$on HAVE_VFORK"
else
	off="$off HAVE_VFORK"
fi

cat >doit.c <<\EOF
main(argc, argv)
int argc;
char **argv;
{
  
  if (argc == 0) {
    int status;
    waitpid(-1, &status, 0);
  }
  exit(0);
}
EOF

if $CC $CFLAGS -o doit doit.c $LIBS >/dev/null 2>&1 && ./doit 2>/dev/null
then
	on="$on HAVE_WAITPID"
else
	off="$off HAVE_WAITPID"
fi

cat >doit.c <<\EOF
#include <string.h>
main(argc, argv)
int argc;
char **argv;
{
  if (argc == 0)
    strerror(0);
  exit(0);
}
EOF

if $CC $CFLAGS -o doit doit.c $LIBS >/dev/null 2>&1 && ./doit 2>/dev/null
then
	off="$off STRERROR_MISSING"
else
	on="$on STRERROR_MISSING"
fi

cat >doit.c <<\EOF
#include <strings.h>
main(argc, argv)
int argc;
char **argv;
{
  if (argc == 0)
	bcopy((char *)0, (char *)0, 0);
  exit(0);
}
EOF

if $CC $CFLAGS -o doit doit.c $LIBS >/dev/null 2>&1 && ./doit 2>/dev/null
then
	# Only use BSD_STRINGS if ANSI string functions don't work.
	cat >doit.c <<\EOF
#include <string.h>
main(argc, argv)
int argc;
char **argv;
{
  if (argc == 0)
	memcpy((char *)0, (char *)0, 0);
  exit(0);
}
EOF

	if $CC $CFLAGS -o doit doit.c $LIBS >/dev/null 2>&1 && ./doit 2>/dev/null
	then
		off="$off BSD_STRINGS"
	else
		on="$on BSD_STRINGS"
	fi
else
	off="$off BSD_STRINGS"
fi

cat >doit.c <<\EOF
#include <signal.h>
main(argc, argv)
int argc;
char **argv;
{
  if (argc == 0)
    raise(SIGINT);  
  exit(0);
}
EOF

if $CC $CFLAGS -o doit doit.c $LIBS >/dev/null 2>&1 && ./doit 2>/dev/null
then
	off="$off RAISE_MISSING"
else
	on="$on RAISE_MISSING"
fi

cat >doit.c <<\EOF
#include <stdio.h>
main(argc, argv)
int argc;
char **argv;
{
  if (argc == 0) {
    fpos_t pos;
    fsetpos(stdin, &pos);
    fgetpos(stdin, &pos);
  }  
  exit(0);
}
EOF

if $CC $CFLAGS -o doit doit.c $LIBS >/dev/null 2>&1 && ./doit 2>/dev/null
then
	off="$off FPOS_MISSING"
else
	on="$on FPOS_MISSING"
fi

cat >doit.c <<\EOF
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

main(argc, argv)
int argc;
char **argv;
{
  if (argc == 0) {
    pid_t pid;
    int status;
    long n = sysconf(_SC_OPEN_MAX);
    pid = waitpid(-1, &status, 0);
    WIFSTOPPED(status);
    WIFSIGNALED(status);
    WIFEXITED(status);
    WEXITSTATUS(status);
    WTERMSIG(status);
    WSTOPSIG(status);
  }
  exit(0);
}
EOF

if $CC $CFLAGS -o doit doit.c $LIBS >/dev/null 2>&1 && ./doit 2>/dev/null
then
	on="$on POSIX"
else
	off="$off POSIX"
fi

cat >doit.c <<\EOF
#include <stdio.h>
#include <signal.h>

static int whoops()
{
  _exit(1);
}

main()
{
  char buf[30];
#ifdef SIGSEGV
  signal(SIGSEGV, whoops);
#endif
#ifdef SIGBUS
  signal(SIGBUS, whoops);
#endif
#ifdef SIGIOT
  signal(SIGIOT, whoops);
#endif
  sprintf(buf, "%2$s%2$s%1$s%1$s", "bar", "foo");
  exit(!!strcmp(buf, "foofoobarbar"));
}
EOF

if $CC $CFLAGS -o doit doit.c $LIBS >/dev/null 2>&1 && ./doit 2>/dev/null
then
	on="$on HAVE_EXTENDED_PRINTF"
else
	off="$off HAVE_EXTENDED_PRINTF"
fi

cat >doit.c <<\EOF
#include <nl_types.h>

main(argc, argv)
int argc;
char **argv;
{
  if (argc == 0) {
    nl_catd d = catopen("foo", 0);
    catgets(d, 1, 1, "default");
    catclose(d);
  }
  exit(0);
}
EOF

if $CC $CFLAGS -o doit doit.c $LIBS >/dev/null 2>&1 && ./doit 2>/dev/null
then
	on="$on HAVE_CAT"
else
	off="$off HAVE_CAT"
fi

cat >doit.c <<\EOF
#include <limits.h>

char c = UCHAR_MAX;

main(argc, argv)
int argc;
char **argv;
{
#if CHAR_MIN < 0
  exit(!(c < 0));
#else
  exit(!(c > 0));
#endif
}
EOF

if $CC $CFLAGS -o doit doit.c $LIBS >/dev/null 2>&1 && ./doit 2>/dev/null
then
	char_signed=
else
	cat >doit.c <<\EOF
main()
{
  int i;

  for (i = 0; i < 512; i++) {
    char c = (char)i;
    if (c < 0)
	exit(1);
  }
  exit(0);
}
EOF

	if $CC $CFLAGS -o doit doit.c $LIBS >/dev/null 2>&1 && ./doit 2>/dev/null
	then
		char_signed=0
	else
		char_signed=1
	fi
fi

cat >doit.c <<\EOF

typedef void VOID;

extern VOID bar();

VOID foo()
{
}
EOF

if $CC $CFLAGS -c doit.c >/dev/null 2>&1
then
	void_ret=void
else
	void_ret=int
fi


cat >doit.c <<\EOF

void *foo()
{
  static char *buf;
  return buf;
}
EOF

if $CC $CFLAGS -c doit.c >doit.log 2>&1
then
	if test -s doit.log
	then
		void_star="char \*"
	else
		void_star="void \*"
	fi

else
	void_star="char \*"
fi

edit=

rm -f doit.c doit doit.log doit.o

for var in $on
do
	edit="$edit -e 's;^/\\* *\\(#define $var [^/]*\\) *\\*/;\\1;'"
done
for var in $off
do
	edit="$edit -e 's;^#define $var [^/]*;/* & */;'"
done

if test -n "$char_signed"
then
	edit="$edit -e 's;^/\\* *\\(#define CHAR_SIGNED $char_signed\\) *\\*/;\\1;'"
fi

edit="$edit -e 's/^typedef .*VOID;/typedef $void_ret VOID;/'"
edit="$edit -e 's/^typedef .*UNIV;/typedef ${void_star}UNIV;/'"

if test "X$(prefix)" != "X/usr/local"
then
	edit="$edit -e '/DEFAULT_PATH/s;/usr/local;$prefix;g'"
fi

eval sed $edit unix.cfg ">config.out"

mv config.out config.h

exit 0
