// gcc/config.d is a generated file
module gcc.config;

private import gcc.builtins;
private import gcc.configext;

// frags-ac.in...


// If long double functions are present, just alias
// to the __builtin_ version.  This may not do the right thing (TODO)

// GCC 3.3 doesn't have some of these builtins
//
extern (C) {
double acos(double);
alias acos acosl;
double asin(double);
alias asin asinl;
double atan(double);
alias atan atanl;
double atan2(double, double);
alias atan2 atan2l;

alias __builtin_cos cosl;
alias __builtin_sin sinl;

double tan(double);
alias tan tanl;
double acosh(double);
alias acosh acoshl;
double asinh(double);
alias asinh asinhl;
double atanh(double);
alias atanh atanhl;
double cosh(double);
alias cosh coshl;
double sinh(double);
alias sinh sinhl;
double tanh(double);
alias tanh tanhl;

alias __builtin_exp expl;

double exp2(double);
alias exp2 exp2l;
double expm1(double);
alias expm1 expm1l;
double frexp(double, bint*);
alias frexp frexpl;
bint ilogb(double);
alias ilogb ilogbl;
double ldexp(double, bint);
alias ldexp ldexpl;

alias __builtin_log logl;

double log10(double);
alias log10 log10l;
double log1p(double);
alias log1p log1pl;
double log2(double);
alias log2 log2l;
double logb(double);
alias logb logbl;

double modf(double, double*);
double modfl(real a, real* b)
{
  double c;
  double result = modf(a, & c);
  *b = c;
  return result;
}

double scalbn(double, bint);
alias scalbn scalbnl;
double scalbln(double, blng);
alias scalbln scalblnl;
double cbrt(double);
alias cbrt cbrtl;
double fabs(double);
alias fabs fabsl;
double hypot(double, double);
alias hypot hypotl;
double pow(double, double);
alias pow powl;

alias __builtin_sqrt sqrtl;

double erf(double);
alias erf erfl;
double erfc(double);
alias erfc erfcl;
double lgamma(double);
alias lgamma lgammal;
double tgamma(double);
alias tgamma tgammal;
double ceil(double);
alias ceil ceill;
double floor(double);
alias floor floorl;
double nearbyint(double);
alias nearbyint nearbyintl;
double rint(double);
alias rint rintl;
blng lrint(double);
alias lrint lrintl;
long llrint(double);
alias llrint llrintl;
double round(double);
alias round roundl;
blng lround(double);
alias lround lroundl;
long llround(double);
alias llround llroundl;
double trunc(double);
alias trunc truncl;
double fmod(double, double);
alias fmod fmodl;
double remainder(double, double);
alias remainder remainderl;
double remquo(double, double, bint*);
alias remquo remquol;
double copysign(double, double);
alias copysign copysignl;

alias __builtin_nan nanl;

double nextafter(double, double);
alias nextafter nextafterl;
double nexttoward(double, double);
alias nexttoward nexttowardl;
double fdim(double, double);
alias fdim fdiml;
double fmax(double, double);
alias fmax fmaxl;
double fmin(double, double);
alias fmin fminl;
double fma(double, double, double);
alias fma fmal;

alias __builtin_sqrt sqrt;
//alias __builtin_sqrtf sqrtf;// needs an extra step
}


alias __builtin_sqrtf sqrtf;

// ...frags-ac.in
// from <stdarg.h>
const size_t va_list_size = 4;


// from <dirent.h>
const size_t dirent_d_name_offset = 20;
const size_t dirent_d_name_size = 256;
const size_t dirent_remaining_size = 0;
const size_t DIR_struct_size = 0;

// from <stdio.h>
const size_t FILE_struct_size = 0;
const int EOF = -1;
const int FOPEN_MAX = 20;
const int FILENAME_MAX = 259;
const int TMP_MAX = 26;
const int L_tmpnam = 259;

// from <sys/types.h>
alias ulong Coff_t;
alias int Csize_t;
alias uint Ctime_t;
extern(C) {

enum {
  FP_NAN = 0,
  FP_INFINITE = 1,
  FP_ZERO = 2,
  FP_SUBNORMAL = 3,
  FP_NORMAL = 4,
}

}


version (darwin)
{
    private struct _XFILE {
	byte[gcc.config.FILE_struct_size] opaque;
    }
    const void * stdin  = &__sF;
    const void * stdout = (ubyte*)&__sF + gcc.config.FILE_struct_size;
    const void * stderr = (ubyte*)&__sF + gcc.config.FILE_struct_size * 2;
}
else version (linux)
{
    alias gcc.configext.stdin stdin;
    alias gcc.configext.stdout stdout;
    alias gcc.configext.stderr stderr;
}
else
{
    extern (C) {
	// make these private?
	void * _d_gnu_cbridge_stdin;
	void * _d_gnu_cbridge_stdout;
	void * _d_gnu_cbridge_stderr;
	void _d_gnu_cbridge_init_stdio();
    }
    alias _d_gnu_cbridge_stdin stdin;
    alias _d_gnu_cbridge_stdout stdout;
    alias _d_gnu_cbridge_stderr stderr;

    static this() {
	_d_gnu_cbridge_init_stdio();
    }
}

// TODO: configurate ?  This is a real mess...
version (linux) {
  // on X86, can use original DMD code, but not on other CPUs...
    version (None) {
      enum {
	FP_NAN,
	FP_INFINITE,
	FP_ZERO,
	FP_SUBNORMAL,
	FP_NORMAL
      }
    }

    extern (C) {
	int __isnan(double);
	int __isnanf(float);
	int __isnanl(real);
	int __isfinite(double);
	int __isfinitef(float);
	int __isfinitel(real);
	int __fpclassify(double);
	int __fpclassifyf(float);
	int __fpclassifyl(real);
	int __isinf(double);
	int __isinff(float);
	int __isinfl(real);
	int __signbit(double);
	int __signbitf(float);
	int __signbitl(real);
    }
  
    int isnan(real x) { return __isnanl(x); }
    int isfinite(real x) { return __isfinitel(x); }
    int isnormal(real x) { return __fpclassifyl(x) == FP_NORMAL; }
    int isnormal(double x) { return __fpclassify(x) == FP_NORMAL; }
    int isnormal(float x) { return __fpclassifyf(x) == FP_NORMAL; }
    int issubnormal(real x) { return __fpclassifyl(x) == FP_SUBNORMAL; }
    int issubnormal(double x) { return __fpclassify(x) == FP_SUBNORMAL; }
    int issubnormal(float x) { return __fpclassifyf(x) == FP_SUBNORMAL; }
    int isinf(real x) { return __isinfl(x); }
    int signbit(real x) { return __signbitl(x); }
    int fpclassify(real x) { return __fpclassifyl(x); }    
    int fpclassify(double x) { return __fpclassify(x); }    
    int fpclassify(float x) { return __fpclassifyf(x); }    

} else version (darwin) {
    // could use direct ieee stuff, but long double/real is a problem
    version (None) {
	enum {
		FP_NAN          = 1,                   /*      NaN                    */
		FP_INFINITE     = 2,                   /*      + or - infinity        */
		FP_ZERO         = 3,                   /*      + or - zero            */
		FP_NORMAL       = 4,                   /*      all normal numbers     */
		FP_SUBNORMAL    = 5                    /*      denormal numbers       */
	}
    }
    
  extern (C) {
      // the 'real' versions are declared, but do not actually exist...
      int __isnand(double);
      int __isnanf(float);
      int __isnan(real);
      int __isfinited(double);
      int __isfinitef(float);
      int __isfinite(real);
      int __isnormald(double);
      int __isnormalf(float);
      int __isnormal(real);
      int __fpclassifyd(double);
      int __fpclassifyf(float);
      int __fpclassify(real);
      int __isinfd(double);
      int __isinff(float);
      int __isinf(real);
      int __signbitd(double);
      int __signbitf(float);
      int __signbitl(real);
  }
  
  int isnan(real x) { return __isnand(x); }
  int isfinite(real x) { return __isfinited(x); }
  int isnormal(real x) { return __isnormald(x); }
  int isnormal(double x) { return __isnormald(x); }
  int isnormal(float x) { return __isnormalf(x); }
  int issubnormal(real x) { return __fpclassifyd(x) == FP_SUBNORMAL; }
  int issubnormal(double x) { return __fpclassifyd(x) == FP_SUBNORMAL; }
  int issubnormal(float x) { return __fpclassifyf(x) == FP_SUBNORMAL; }
  int isinf(real x) { return __isinfd(x); }
  int signbit(real x) { return __signbitd(x); }
  int fpclassify(real x) { return __fpclassifyd(x); }    
  int fpclassify(double x) { return __fpclassifyd(x); }    
  int fpclassify(float x) { return __fpclassifyf(x); }    
} else {
    // %%TODO: slightly better: test which of __fpclassify[fdl<null>] exist
    // and use those.  Could do the same with __is
    extern (C) {
	int _d_gnu_cbridge_fpclassifyl(real);
	int _d_gnu_cbridge_fpclassifyd(double);
	int _d_gnu_cbridge_fpclassifyf(float);
	int _d_gnu_cbridge_signbitl(real);
	int _d_gnu_cbridge_signbitd(double);
	int _d_gnu_cbridge_signbitf(float);
    }
    int isnan(real x) { return _d_gnu_cbridge_fpclassifyl(x)==FP_NAN; }
    int isfinite(real x) {
	int r = _d_gnu_cbridge_fpclassifyl(x);
	return r != FP_NAN && r != FP_INFINITE;
    }
    int isnormal(real x) { return _d_gnu_cbridge_fpclassifyl(x)==FP_NORMAL; }
    int isnormal(double x) { return _d_gnu_cbridge_fpclassifyd(x)==FP_NORMAL; }
    int isnormal(float x) { return _d_gnu_cbridge_fpclassifyf(x)==FP_NORMAL; }
    int issubnormal(real x) { return _d_gnu_cbridge_fpclassifyl(x) == FP_SUBNORMAL; }
    int issubnormal(double x) { return _d_gnu_cbridge_fpclassifyd(x) == FP_SUBNORMAL; }
    int issubnormal(float x) { return _d_gnu_cbridge_fpclassifyf(x) == FP_SUBNORMAL; }
    int isinf(real x) { return _d_gnu_cbridge_fpclassifyl(x)==FP_INFINITE; }
    int signbit(real x) { return _d_gnu_cbridge_signbitl(x)==FP_NAN; }
    int fpclassify(real x) { return _d_gnu_cbridge_fpclassifyl(x); }
    int fpclassify(double x) { return _d_gnu_cbridge_fpclassifyd(x); }
    int fpclassify(float x) { return _d_gnu_cbridge_fpclassifyf(x); }
}

// TODO: configure these
private import std.c.stdio;
extern (C) int ferror(FILE *);
extern (C) int feof(FILE *);
extern (C) void clearerr(FILE *);
extern (C) void rewind(FILE *);
extern (C) int _bufsize(FILE *);
extern (C) int fileno(FILE *);

alias __builtin_snprintf Csnprintf;
alias __builtin_vsnprintf Cvsnprintf;
alias __builtin_snprintf C_snprintf;
alias __builtin_vsnprintf C_vsnprintf;

alias ubyte* Cva_list; // 'va_list' causes problems later...
alias __builtin_va_start Cva_start;
