/* libconfig.c:
 *
 * this performs tests to configure external libraries.  most of these
 * tests are used to determine a compiler's configuration.  output
 * files are written into <libname>.conf for inclusion by a Makefile.
 *
 * jim frost 09.15.93
 */
#include <stdio.h>

/* things determined by compilation switches
 */
#ifdef __STDC__
/* ANSI versus non-ANSI.  Note that some compilers define __STDC__
 * as zero when they are not fully ANSI-compliant.  We don't care,
 * it's close enough.
 */
int is_ansi = 1;
#else
int is_ansi = 0;
#endif
#if defined(IS_BSD)
int is_bsd = 1;
#else
int is_bsd = 0;
#endif

/* things determined on-the-fly
 */
int is_big_endian;
int is_signed_char;
int is_broken_right_shift;

#ifdef HAS_TIFF
void writeTIFFConfig()
{
  FILE *f;

  f = fopen("tiff.conf", "w");
  if (f == NULL) {
    perror("tiff.conf");
    fprintf(stderr, "libconfig: Couldn't write TIFF library config, sorry.\n");
    return;
  }
  printf("Writing TIFF library configuration file....\n");
  fprintf(f, "\
# TIFF distribution configuration file; this is automagically configured by\n\
# 'libconfig.'  If you must edit it, beware that reconfiguring the\n\
# distribution with rewrite this file.\n\n");

  fprintf(f, "# Get system-configuration stuff\n");
  fprintf(f, "include ../Make.conf\n\n");

  fprintf(f, "# ANSI compatibility flags\n");
  fprintf(f, "%sPROTOTYPES=-DUSE_PROTOTYPES\n", (is_ansi ? "" : "#"));
  fprintf(f, "%sVARARGS=-DUSE_VARARGS\n", (is_ansi ? "#" : ""));
  fprintf(f, "%sCONST=-DUSE_CONST\n", (is_ansi ? "" : "#"));
  fprintf(f, "\n");

  fprintf(f, "# If not a BSD system, need -DSYSV to fix bcopy et al.\n");
  fprintf(f, "%sSYSV=-DSYSV\n\n", (is_bsd ? "#" : ""));

  fprintf(f, "# Conglomerate of all TIFF flags\n");
  fprintf(f, "TIFF_CC_FLAGS=$(PROTOTYPES) $(VARARGS) $(CONST) $(SYSV) -Dunix\n");
  fclose(f);
}
#endif /* HAS_TIFF */

#ifdef HAS_JPEG
void writeJPEGConfig()
{
  FILE *f;

  f = fopen("jpeg.conf", "w");
  if (f == NULL) {
    perror("jpeg.conf");
    fprintf(stderr, "libconfig: Couldn't write JPEG library config, sorry.\n");
    return;
  }
  printf("Writing JPEG library configuration file....\n");
  fprintf(f, "\
# JPEG distribution configuration file; this is automagically configured by\n\
# 'libconfig.'  If you must edit it, beware that reconfiguring the\n\
# distribution with rewrite this file and that changes made here must be\n\
# reflected in jpeg.conf.h.\n\n");

  fprintf(f, "# Get system-configuration stuff\n");
  fprintf(f, "include ../Make.conf\n\n");

  fprintf(f, "# SysV or not.\n");
  fprintf(f, "%sSYSV=-DSYSV\n\n", (is_bsd ? "#" : ""));

  fprintf(f, "# ANSI compatibility flags\n");
  fprintf(f, "%sANSI=-DHAS_STDC\n\n", (is_ansi ? "" : "#"));

  fprintf(f, "# Default signed-ness of char type\n");
  fprintf(f, "%sUNSIGNED_CHAR=-DCHAR_IS_UNSIGNED\n\n", (is_signed_char ? "#" : ""));

  fprintf(f, "# We need to know if the compiler has a broken right-shift operator\n");
  fprintf(f, "%sBROKEN_SHIFT=-DRIGHT_SHIFT_IS_UNSIGNED\n\n", (is_broken_right_shift ? "" : "#"));

  fprintf(f, "# Extra flags we need\n");
  fprintf(f, "OTHER=%s\n\n", (is_ansi ? "" : "-DHAVE_UNSIGNED_CHAR"));

  fprintf(f, "# Conglomerate of all JPEG flags\n\n");
  fprintf(f, "JPEG_CC_FLAGS=$(OPT_FLAGS) $(SYSV) $(ANSI) $(UNSIGNED_CHAR) $(BROKEN_SHIFT) $(OTHER)\n");

  /* JPEG stuff is all ANSI; we need to write out a .c.o target that
   * does the compilation correctly if either ANSI or K&R
   */
  fprintf(f, "# .c to .o target; special work needs to be done if not an ANSI compiler.\n");
  if (is_ansi) {
    fprintf(f, ".c.o:\n");
    fprintf(f, "\t$(CC) $(JPEG_CC_FLAGS) -c $*.c\n");
  }
  else {
    fprintf(f, ".c.o: ./ansi2knr\n");
    fprintf(f, "\t./ansi2knr $*.c tmpansi.c\n");
    fprintf(f, "\t$(CC) $(JPEG_CC_FLAGS) -c tmpansi.c\n");
    fprintf(f, "\t$(MV) tmpansi.o $*.o\n");
    fprintf(f, "\t$(RM) tmpansi.c\n");
  }
  fclose(f);

  /* write jpeg.conf.h, used by jpeg.c to get the same defines as used by
   * the library.
   */
  f = fopen("jpeg.conf.h", "w");
  if (f == NULL) {
    perror("jpeg.conf");
    fprintf(stderr, "libconfig: Couldn't write JPEG configuration header, sorry.\n");
    return;
  }
  /* -DSYSV already done in Make.conf */
  fprintf(f, "\
/* jpeg.conf.h:\n\
 *\n\
 * Configuration file that matches the Makefile configuration file jpeg.conf\n\
 * for building jpeg.c.  This file is automatically generated.\n\
 */\n\n");
  fprintf(f, "#define HAVE_UNSIGNED_CHAR 1\n");
  if (is_ansi) {
    fprintf(f, "#define PROTO 1\n");
    fprintf(f, "#define HAS_STDC 1\n");
  }
  if (!is_signed_char)
    fprintf(f, "#define CHAR_IS_UNSIGNED 1\n");
  if (is_broken_right_shift)
    fprintf(f, "#define RIGHT_SHIFT_IS_UNSIGNED 1\n");
  fclose(f);
}
#endif /* HAS_JPEG */

main()
{ union {
    unsigned short s;
    char c[2];
  } byte_test;
  char c = 0;
  int i;

  if (is_ansi)
    printf("C compiler recognizes ANSI constructs.\n");
  else
    printf("C compiler is not ANSI-compatible.\n");

  /* determine machine byte order
   */
  byte_test.s = 0x00ff;
  if (byte_test.c[0] == 0) {
    printf("Machine has big-endian byte order.\n");
    is_big_endian = 1;
  }
  else {
    printf("Machine has little-endian byte order.\n");
    is_big_endian = 0;
  }

  /* determine default signed-ness of characters.
   */
  if (--c > 0) { /* will wrap to 255 if unsigned */
    printf("Compiler assumes unsigned characters by default.\n");
    is_signed_char = 0;
  }
  else {
    printf("Compiler assumes signed characters by default.\n");
    is_signed_char = 1;
  }

  /* determine if the compiler stupidly handles right-shift as a logical
   * shift rather than an arithmetic shift.  this would be broken
   * behavior but JPEG wants to know....
   */
  i = -1;
  if ((i >> 1) > 0) {
    printf("\
Compiler stupidly treats a signed right-shift as a logical operation.\n");
    is_broken_right_shift = 1;
  }
  else
    is_broken_right_shift = 0;

#ifdef HAS_TIFF
  writeTIFFConfig();
#endif
#ifdef HAS_JPEG
  writeJPEGConfig();
#endif

  exit(0);
}
