Commits

Johannes Pfau committed 883c039

Move config & gcc files

This time from the correct phobos directory

Comments (0)

Files changed (64)

d/druntime/config/errno.x3

+// this is not really unix, is it?
+x3_out_text(""
+    "module gcc.config.errno;\n");
+
+x3_gi_push_header("<errno.h>");
+x3_out_enum(NULL, NULL, "^E[^_].*", NULL);
+x3_gi_pop_header();

d/druntime/config/fpcls.x3

+x3_out_text(""
+    "module gcc.config.fpcls;\n");
+
+x3_gi_push_header("\"config.h\"");
+x3_gi_push_header("<math.h>");
+x3_out_enum(NULL, NULL, "^FP_[^_].*", "-^FP_ILOG.*", NULL);
+x3_gi_pop_header();

d/druntime/config/ldfuncs

+// If long double functions are present, just alias
+// to the __builtin_ version.  This may not do the right thing (TODO)
+extern (C) { // prob doesn't matter..
+alias __builtin_acosl acosl;
+alias __builtin_asinl asinl;
+alias __builtin_atanl atanl;
+alias __builtin_atan2l atan2l;
+alias __builtin_cosl cosl;
+alias __builtin_sinl sinl;
+alias __builtin_tanl tanl;
+alias __builtin_acoshl acoshl;
+alias __builtin_asinhl asinhl;
+alias __builtin_atanhl atanhl;
+alias __builtin_coshl coshl;
+alias __builtin_sinhl sinhl;
+alias __builtin_tanhl tanhl;
+alias __builtin_expl expl;
+alias __builtin_exp2l exp2l;
+alias __builtin_expm1l expm1l;
+alias __builtin_frexpl frexpl;
+alias __builtin_ilogbl ilogbl;
+alias __builtin_ldexpl ldexpl;
+alias __builtin_logl logl;
+alias __builtin_log10l log10l;
+alias __builtin_log1pl log1pl;
+alias __builtin_log2l log2l;
+alias __builtin_logbl logbl;
+alias __builtin_modfl modfl;
+alias __builtin_scalbnl scalbnl;
+alias __builtin_scalblnl scalblnl;
+alias __builtin_cbrtl cbrtl;
+alias __builtin_fabsl fabsl;
+alias __builtin_hypotl hypotl;
+alias __builtin_powl powl;
+alias __builtin_sqrtl sqrtl;
+alias __builtin_erfl erfl;
+alias __builtin_erfcl erfcl;
+alias __builtin_lgammal lgammal;
+alias __builtin_tgammal tgammal;
+alias __builtin_ceill ceill;
+alias __builtin_floorl floorl;
+alias __builtin_nearbyintl nearbyintl;
+alias __builtin_rintl rintl;
+alias __builtin_lrintl lrintl;
+alias __builtin_llrintl llrintl;
+alias __builtin_roundl roundl;
+alias __builtin_lroundl lroundl;
+alias __builtin_llroundl llroundl;
+alias __builtin_truncl truncl;
+alias __builtin_fmodl fmodl;
+alias __builtin_remainderl remainderl;
+alias __builtin_remquol remquol;
+alias __builtin_copysignl copysignl;
+//alias __builtin_nanl nanl;
+real nanl(in char *);
+alias __builtin_nextafterl nextafterl;
+alias __builtin_nexttowardl nexttowardl;
+alias __builtin_fdiml fdiml;
+alias __builtin_fmaxl fmaxl;
+alias __builtin_fminl fminl;
+alias __builtin_fmal fmal;
+
+alias __builtin_sqrt sqrt;
+//alias __builtin_sqrtf sqrtf;// needs an extra step
+}

d/druntime/config/ldfuncs-darwin

+
+private import gcc.ldblcompat;
+
+extern (C) {
+
+real acosl( real ); pragma(GNU_asm,acosl,"acosl" ~ __LIBMLDBL_COMPAT);
+real asinl( real ); pragma(GNU_asm,asinl,"asinl" ~ __LIBMLDBL_COMPAT);
+real atanl( real ); pragma(GNU_asm,atanl,"atanl" ~ __LIBMLDBL_COMPAT);
+real atan2l( real, real ); pragma(GNU_asm,atan2l,"atan2l" ~ __LIBMLDBL_COMPAT);
+real cosl( real ); pragma(GNU_asm,cosl,"cosl" ~ __LIBMLDBL_COMPAT);
+real sinl( real ); pragma(GNU_asm,sinl,"sinl" ~ __LIBMLDBL_COMPAT);
+real tanl( real ); pragma(GNU_asm,tanl,"tanl" ~ __LIBMLDBL_COMPAT);
+real acoshl( real ); pragma(GNU_asm,acoshl,"acoshl" ~ __LIBMLDBL_COMPAT);
+real asinhl( real ); pragma(GNU_asm,asinhl,"asinhl" ~ __LIBMLDBL_COMPAT);
+real atanhl( real ); pragma(GNU_asm,atanhl,"atanhl" ~ __LIBMLDBL_COMPAT);
+real coshl( real ); pragma(GNU_asm,coshl,"coshl" ~ __LIBMLDBL_COMPAT);
+real sinhl( real ); pragma(GNU_asm,sinhl,"sinhl" ~ __LIBMLDBL_COMPAT);
+real tanhl( real ); pragma(GNU_asm,tanhl,"tanhl" ~ __LIBMLDBL_COMPAT);
+real expl( real ); pragma(GNU_asm,expl,"expl" ~ __LIBMLDBL_COMPAT);
+real exp2l( real ); pragma(GNU_asm,exp2l,"exp2l" ~ __LIBMLDBL_COMPAT);
+real expm1l( real ); pragma(GNU_asm,expm1l,"expm1l" ~ __LIBMLDBL_COMPAT);
+real logl( real ); pragma(GNU_asm,logl,"logl" ~ __LIBMLDBL_COMPAT);
+real log10l( real ); pragma(GNU_asm,log10l,"log10l" ~ __LIBMLDBL_COMPAT);
+real log2l( real ); pragma(GNU_asm,log2l,"log2l" ~ __LIBMLDBL_COMPAT);
+real log1pl( real ); pragma(GNU_asm,log1pl,"log1pl" ~ __LIBMLDBL_COMPAT);
+real logbl( real ); pragma(GNU_asm,logbl,"logbl" ~ __LIBMLDBL_COMPAT);
+real modfl( real, real * ); pragma(GNU_asm,modfl,"modfl" ~ __LIBMLDBL_COMPAT);
+real ldexpl( real, int ); pragma(GNU_asm,ldexpl,"ldexpl" ~ __LIBMLDBL_COMPAT);
+real frexpl( real, int * ); pragma(GNU_asm,frexpl,"frexpl" ~ __LIBMLDBL_COMPAT);
+int ilogbl( real ); pragma(GNU_asm,ilogbl,"ilogbl" ~ __LIBMLDBL_COMPAT);
+real scalbnl( real, int ); pragma(GNU_asm,scalbnl,"scalbnl" ~ __LIBMLDBL_COMPAT);
+real scalblnl( real, __builtin_Clong ); pragma(GNU_asm,scalblnl,"scalblnl" ~ __LIBMLDBL_COMPAT);
+real fabsl( real ); pragma(GNU_asm,fabsl,"fabsl" ~ __LIBMLDBL_COMPAT);
+real cbrtl( real ); pragma(GNU_asm,cbrtl,"cbrtl" ~ __LIBMLDBL_COMPAT);
+real hypotl( real, real ); pragma(GNU_asm,hypotl,"hypotl" ~ __LIBMLDBL_COMPAT);
+real powl( real, real ); pragma(GNU_asm,powl,"powl" ~ __LIBMLDBL_COMPAT);
+real sqrtl( real ); pragma(GNU_asm,sqrtl,"sqrtl" ~ __LIBMLDBL_COMPAT);
+real erfl( real ); pragma(GNU_asm,erfl,"erfl" ~ __LIBMLDBL_COMPAT);
+real erfcl( real ); pragma(GNU_asm,erfcl,"erfcl" ~ __LIBMLDBL_COMPAT);
+real lgammal( real ); pragma(GNU_asm,lgammal,"lgammal" ~ __LIBMLDBL_COMPAT);
+real tgammal( real ); pragma(GNU_asm,tgammal,"tgammal" ~ __LIBMLDBL_COMPAT);
+real ceill( real ); pragma(GNU_asm,ceill,"ceill" ~ __LIBMLDBL_COMPAT);
+real floorl( real ); pragma(GNU_asm,floorl,"floorl" ~ __LIBMLDBL_COMPAT);
+real nearbyintl( real ); pragma(GNU_asm,nearbyintl,"nearbyintl" ~ __LIBMLDBL_COMPAT);
+real rintl( real ); pragma(GNU_asm,rintl,"rintl" ~ __LIBMLDBL_COMPAT);
+__builtin_Clong lrintl( real ); pragma(GNU_asm,lrintl,"lrintl" ~ __LIBMLDBL_COMPAT);
+long llrintl( real ); pragma(GNU_asm,llrintl,"llrintl" ~ __LIBMLDBL_COMPAT);
+real roundl( real ); pragma(GNU_asm,roundl,"roundl" ~ __LIBMLDBL_COMPAT);
+__builtin_Clong lroundl( real ); pragma(GNU_asm,lroundl,"lroundl" ~ __LIBMLDBL_COMPAT);
+long llroundl( real ); pragma(GNU_asm,llroundl,"llroundl" ~ __LIBMLDBL_COMPAT);
+real truncl( real ); pragma(GNU_asm,truncl,"truncl" ~ __LIBMLDBL_COMPAT);
+real fmodl( real, real); pragma(GNU_asm,fmodl,"fmodl" ~ __LIBMLDBL_COMPAT);
+real remainderl( real, real ); pragma(GNU_asm,remainderl,"remainderl" ~ __LIBMLDBL_COMPAT);
+real remquol( real, real, int * ); pragma(GNU_asm,remquol,"remquol" ~ __LIBMLDBL_COMPAT);
+real copysignl( real, real ); pragma(GNU_asm,copysignl,"copysignl" ~ __LIBMLDBL_COMPAT);
+real nanl( in char * ); pragma(GNU_asm,nanl,"nanl" ~ __LIBMLDBL_COMPAT);
+real nextafterl( real, real ); pragma(GNU_asm,nextafterl,"nextafterl" ~ __LIBMLDBL_COMPAT);
+double nexttoward( double, real ); pragma(GNU_asm,nexttoward,"nexttoward" ~ __LIBMLDBL_COMPAT);
+float nexttowardf( float, real ); pragma(GNU_asm,nexttowardf,"nexttowardf" ~ __LIBMLDBL_COMPAT);
+real nexttowardl( real, real ); pragma(GNU_asm,nexttowardl,"nexttowardl" ~ __LIBMLDBL_COMPAT);
+real fdiml( real, real ); pragma(GNU_asm,fdiml,"fdiml" ~ __LIBMLDBL_COMPAT);
+real fmaxl( real, real ); pragma(GNU_asm,fmaxl,"fmaxl" ~ __LIBMLDBL_COMPAT);
+real fminl( real, real ); pragma(GNU_asm,fminl,"fminl" ~ __LIBMLDBL_COMPAT);
+real fmal( real, real, real ); pragma(GNU_asm,fmal,"fmal" ~ __LIBMLDBL_COMPAT);
+
+/*
+
+pragma(GNU_asm,"_acosl" ~ __LIBMLDBL_COMPAT) real acosl( real );
+pragma(GNU_asm,"_asinl" ~ __LIBMLDBL_COMPAT) real asinl( real );
+pragma(GNU_asm,"_atanl" ~ __LIBMLDBL_COMPAT) real atanl( real );
+pragma(GNU_asm,"_atan2l" ~ __LIBMLDBL_COMPAT) real atan2l( real, real );
+pragma(GNU_asm,"_cosl" ~ __LIBMLDBL_COMPAT) real cosl( real );
+pragma(GNU_asm,"_sinl" ~ __LIBMLDBL_COMPAT) real sinl( real );
+pragma(GNU_asm,"_tanl" ~ __LIBMLDBL_COMPAT) real tanl( real );
+pragma(GNU_asm,"_acoshl" ~ __LIBMLDBL_COMPAT) real acoshl( real );
+pragma(GNU_asm,"_asinhl" ~ __LIBMLDBL_COMPAT) real asinhl( real );
+pragma(GNU_asm,"_atanhl" ~ __LIBMLDBL_COMPAT) real atanhl( real );
+pragma(GNU_asm,"_coshl" ~ __LIBMLDBL_COMPAT) real coshl( real );
+pragma(GNU_asm,"_sinhl" ~ __LIBMLDBL_COMPAT) real sinhl( real );
+pragma(GNU_asm,"_tanhl" ~ __LIBMLDBL_COMPAT) real tanhl( real );
+pragma(GNU_asm,"_expl" ~ __LIBMLDBL_COMPAT) real expl( real );
+pragma(GNU_asm,"_exp2l" ~ __LIBMLDBL_COMPAT) real exp2l( real );
+pragma(GNU_asm,"_expm1l" ~ __LIBMLDBL_COMPAT) real expm1l( real );
+pragma(GNU_asm,"_logl" ~ __LIBMLDBL_COMPAT) real logl( real );
+pragma(GNU_asm,"_log10l" ~ __LIBMLDBL_COMPAT) real log10l( real );
+pragma(GNU_asm,"_log2l" ~ __LIBMLDBL_COMPAT) real log2l( real );
+pragma(GNU_asm,"_log1pl" ~ __LIBMLDBL_COMPAT) real log1pl( real );
+pragma(GNU_asm,"_logbl" ~ __LIBMLDBL_COMPAT) real logbl( real );
+pragma(GNU_asm,"_modfl" ~ __LIBMLDBL_COMPAT) real modfl( real, real * );
+pragma(GNU_asm,"_ldexpl" ~ __LIBMLDBL_COMPAT) real ldexpl( real, int );
+pragma(GNU_asm,"_frexpl" ~ __LIBMLDBL_COMPAT) real frexpl( real, int * );
+pragma(GNU_asm,"_ilogbl" ~ __LIBMLDBL_COMPAT)  int ilogbl( real );
+pragma(GNU_asm,"_scalbnl" ~ __LIBMLDBL_COMPAT) real scalbnl( real, int );
+pragma(GNU_asm,"_scalblnl" ~ __LIBMLDBL_COMPAT) real scalblnl( real, __builtin_Clong );
+pragma(GNU_asm,"_fabsl" ~ __LIBMLDBL_COMPAT) real fabsl( real );
+pragma(GNU_asm,"_cbrtl" ~ __LIBMLDBL_COMPAT) real cbrtl( real );
+pragma(GNU_asm,"_hypotl" ~ __LIBMLDBL_COMPAT) real hypotl( real, real );
+pragma(GNU_asm,"_powl" ~ __LIBMLDBL_COMPAT) real powl( real, real );
+pragma(GNU_asm,"_sqrtl" ~ __LIBMLDBL_COMPAT) real sqrtl( real );
+pragma(GNU_asm,"_erfl" ~ __LIBMLDBL_COMPAT) real erfl( real );
+pragma(GNU_asm,"_erfcl" ~ __LIBMLDBL_COMPAT) real erfcl( real );
+pragma(GNU_asm,"_lgammal" ~ __LIBMLDBL_COMPAT) real lgammal( real );
+pragma(GNU_asm,"_tgammal" ~ __LIBMLDBL_COMPAT) real tgammal( real );
+pragma(GNU_asm,"_ceill" ~ __LIBMLDBL_COMPAT) real ceill( real );
+pragma(GNU_asm,"_floorl" ~ __LIBMLDBL_COMPAT) real floorl( real );
+pragma(GNU_asm,"_nearbyintl" ~ __LIBMLDBL_COMPAT) real nearbyintl( real );
+pragma(GNU_asm,"_rintl" ~ __LIBMLDBL_COMPAT) real rintl( real );
+pragma(GNU_asm,"_lrintl" ~ __LIBMLDBL_COMPAT)  __builtin_Clong lrintl( real );
+pragma(GNU_asm,"_llrintl" ~ __LIBMLDBL_COMPAT)  long llrintl( real );
+pragma(GNU_asm,"_roundl" ~ __LIBMLDBL_COMPAT) real roundl( real );
+pragma(GNU_asm,"_lroundl" ~ __LIBMLDBL_COMPAT)  __builtin_Clong lroundl( real );
+pragma(GNU_asm,"_llroundl" ~ __LIBMLDBL_COMPAT)  long llroundl( real );
+pragma(GNU_asm,"_truncl" ~ __LIBMLDBL_COMPAT) real truncl( real );
+pragma(GNU_asm,"_fmodl" ~ __LIBMLDBL_COMPAT) real fmodl( real, real);
+pragma(GNU_asm,"_remainderl" ~ __LIBMLDBL_COMPAT) real remainderl( real, real );
+pragma(GNU_asm,"_remquol" ~ __LIBMLDBL_COMPAT) real remquol( real, real, int * );
+pragma(GNU_asm,"_copysignl" ~ __LIBMLDBL_COMPAT) real copysignl( real, real );
+pragma(GNU_asm,"_nanl" ~ __LIBMLDBL_COMPAT) real nanl( const char * );
+pragma(GNU_asm,"_nextafterl" ~ __LIBMLDBL_COMPAT) real nextafterl( real, real );
+pragma(GNU_asm,"_nexttoward" ~ __LIBMLDBL_COMPAT)  double nexttoward( double, real );
+pragma(GNU_asm,"_nexttowardf" ~ __LIBMLDBL_COMPAT)  float nexttowardf( float, real );
+pragma(GNU_asm,"_nexttowardl" ~ __LIBMLDBL_COMPAT) real nexttowardl( real, real );
+pragma(GNU_asm,"_fdiml" ~ __LIBMLDBL_COMPAT) real fdiml( real, real );
+pragma(GNU_asm,"_fmaxl" ~ __LIBMLDBL_COMPAT) real fmaxl( real, real );
+pragma(GNU_asm,"_fminl" ~ __LIBMLDBL_COMPAT) real fminl( real, real );
+pragma(GNU_asm,"_fmal" ~ __LIBMLDBL_COMPAT) real fmal( real, real, real );
+*/
+
+alias __builtin_sqrt sqrt;
+}

d/druntime/config/ldfuncs-ppclinux

+
+private import gcc.ldblcompat;
+
+extern (C) {
+
+static if (__No_Long_Double_Math)
+{
+real acos( double ); alias acos acosl;
+real asin( double ); alias asin asinl;
+real atan( double ); alias atan atanl;
+real atan2( double, double ); alias atan2 atan2l;
+real cos( double ); alias cos cosl;
+real sin( double ); alias sin sinl;
+real tan( double ); alias tan tanl;
+real acosh( double ); alias acosh acoshl;
+real asinh( double ); alias asinh asinhl;
+real atanh( double ); alias atanh atanhl;
+real cosh( double ); alias cosh coshl;
+real sinh( double ); alias sinh sinhl;
+real tanh( double ); alias tanh tanhl;
+real exp( double ); alias exp expl;
+real exp2( double ); alias exp2 exp2l;
+real expm1( double ); alias expm1 expm1l;
+real log( double ); alias log logl;
+real log10( double ); alias log10 log10l;
+real log2( double ); alias log2 log2l;
+real log1p( double ); alias log1p log1pl;
+real logb( double ); alias logb logbl;
+
+double modf(double, double*);
+extern (D) real modfl(real x, real * py) {
+    double dx = x;
+    double y;
+    double result = modf(dx, & y);
+    *py = y;
+    return result;
+}
+
+real ldexp( double, int ); alias ldexp ldexpl;
+real frexp( double, int * ); alias frexp frexpl;
+int ilogb( double ); alias ilogb ilogbl;
+real scalbn( double, int ); alias scalbn scalbnl;
+real scalbln( double, Clong_t ); alias scalbln scalblnl;
+real fabs( double ); alias fabs fabsl;
+real cbrt( double ); alias cbrt cbrtl;
+real hypot( double, double ); alias hypot hypotl;
+real pow( double, double ); alias pow powl;
+real sqrt( double ); alias sqrt sqrtl;
+real erf( double ); alias erf erfl;
+real erfc( double ); alias erfc erfcl;
+real lgamma( double ); alias lgamma lgammal;
+real tgamma( double ); alias tgamma tgammal;
+real ceil( double ); alias ceil ceill;
+real floor( double ); alias floor floorl;
+real nearbyint( double ); alias nearbyint nearbyintl;
+real rint( double ); alias rint rintl;
+Clong_t lrint( double ); alias lrint lrintl;
+long llrint( double ); alias llrint llrintl;
+real round( double ); alias round roundl;
+Clong_t lround( double ); alias lround lroundl;
+long llround( double ); alias llround llroundl;
+real trunc( double ); alias trunc truncl;
+real fmod( double, real); alias fmod fmodl;
+real remainder( double, double ); alias remainder remainderl;
+real remquo( double, double, int * ); alias remquo remquol;
+real copysign( double, double ); alias copysign copysignl;
+real nan( in char * ); alias nan nanl;
+real nextafter( double, double );
+alias nextafter nextafterl;
+alias nextafter nexttowardl;
+real fdim( double, double ); alias fdim fdiml;
+real fmax( double, double ); alias fmax fmaxl;
+real fmin( double, double ); alias fmin fminl;
+real fma( double, double, double ); alias fma fmal;
+}
+else
+{
+real acosl( real );
+real asinl( real );
+real atanl( real );
+real atan2l( real, real );
+real cosl( real );
+real sinl( real );
+real tanl( real );
+real acoshl( real );
+real asinhl( real );
+real atanhl( real );
+real coshl( real );
+real sinhl( real );
+real tanhl( real );
+real expl( real );
+real exp2l( real );
+real expm1l( real );
+real logl( real );
+real log10l( real );
+real log2l( real );
+real log1pl( real );
+real logbl( real );
+real modfl( real, real * );
+real ldexpl( real, int );
+real frexpl( real, int * );
+int ilogbl( real );
+real scalbnl( real, int );
+real scalblnl( real, Clong_t );
+real fabsl( real );
+real cbrtl( real );
+real hypotl( real, real );
+real powl( real, real );
+real sqrtl( real );
+real erfl( real );
+real erfcl( real );
+real lgammal( real );
+real tgammal( real );
+real ceill( real );
+real floorl( real );
+real nearbyintl( real );
+real rintl( real );
+Clong_t lrintl( real );
+long llrintl( real );
+real roundl( real );
+Clong_t lroundl( real );
+long llroundl( real );
+real truncl( real );
+real fmodl( real, real);
+real remainderl( real, real );
+real remquol( real, real, int * );
+real copysignl( real, real );
+real nanl( in char * );
+real nextafterl( real, real );
+double nexttoward( double, real );
+float nexttowardf( float, real );
+real nexttowardl( real, real );
+real fdiml( real, real );
+real fmaxl( real, real );
+real fminl( real, real );
+real fmal( real, real, real );
+
+double sqrt(double);
+}
+
+}

d/druntime/config/libc.x3

+x3_out_text(""
+    "module gcc.config.libc;\n"
+    "private import gcc.builtins;\n"
+    "\n"
+    "//alias __builtin_Clong Clong_t;\n"
+    "//alias __builtin_Culong Culong_t;\n");
+
+x3_gi_push_header("\"config.h\"");
+x3_gi_push_header("<sys/types.h>");
+x3_out_int_type("off_t");
+
+
+x3_gi_push_header("<stddef.h>");
+x3_out_char_type("wchar_t");
+x3_gi_pop_header();
+
+x3_gi_push_header("<time.h>");
+//x3_gi_push_header("<sys/time.h>");//?
+x3_out_int_type("time_t");
+x3_out_int_type("clock_t");
+x3_out_int_value_ex("CLOCKS_PER_SEC", NULL, "unsigned int", "uint", 0, NULL);
+x3_out_struct("struct tm", NULL, "i:tm_sec", "i:tm_min", "i:tm_hour",
+    "i:tm_mday", "i:tm_mon", "i:tm_year", "i:tm_wday", "i:tm_yday",
+    "i:tm_isdst", "oi:tm_gmtoff", "otchar *;:tm_zone", NULL);
+x3_gi_pop_header();
+
+x3_gi_push_header("<stdlib.h>");
+x3_out_int_value("RAND_MAX");
+x3_gi_pop_header();
+
+x3_gi_push_header("<stdio.h>");
+x3_gi_push_header("<limits.h>");
+x3_out_int_value("EOF");
+x3_out_int_value("FILENAME_MAX"); // find the deps.. aare these really needed?
+x3_out_int_value("TMP_MAX");
+x3_push_optional(1);
+x3_out_int_value("FOPEN_MAX");
+x3_out_int_value("L_tmpnam");
+x3_out_int_value("BUFSIZ");
+x3_pop_optional(1);
+
+// want to get rid of this...
+x3_out_int_value_ex("FILE_struct_size", "sizeof(FILE)", "size_t", NULL, 0, "0");
+
+x3_out_type("fpos_t");
+
+x3_gi_pop_headers(2);

d/druntime/config/noldfuncs

+// We don't have long double functions..
+
+extern (C) { // prob doesn't matter..
+alias __builtin_acos acosl;
+alias __builtin_asin asinl;
+alias __builtin_atan atanl;
+alias __builtin_atan2 atan2l;
+alias __builtin_cos cosl;
+alias __builtin_sin sinl;
+alias __builtin_tan tanl;
+alias __builtin_acosh acoshl;
+alias __builtin_asinh asinhl;
+alias __builtin_atanh atanhl;
+alias __builtin_cosh coshl;
+alias __builtin_sinh sinhl;
+alias __builtin_tanh tanhl;
+alias __builtin_exp expl;
+alias __builtin_exp2 exp2l;
+alias __builtin_expm1 expm1l;
+
+alias __builtin_frexp frexpl;
+
+alias __builtin_ilogb ilogbl;
+alias __builtin_ldexp ldexpl;
+alias __builtin_log logl;
+alias __builtin_log10 log10l;
+alias __builtin_log1p log1pl;
+alias __builtin_log2 log2l;
+alias __builtin_logb logbl;
+
+//alias gcc.config.modfl __builtin_modf;
+extern (D) real modfl(real x, real * py) {
+    double dx = x;
+    double y;
+    double result = __builtin_modf(dx, & y);
+    *py = y;
+    return result;
+}
+
+alias __builtin_scalbn scalbnl;
+alias __builtin_scalbln scalblnl;
+alias __builtin_cbrt cbrtl;
+alias __builtin_fabs fabsl;
+alias __builtin_hypot hypotl;
+alias __builtin_pow powl;
+alias __builtin_sqrt sqrtl;
+alias __builtin_erf erfl;
+alias __builtin_erfc erfcl;
+alias __builtin_lgamma lgammal;
+alias __builtin_tgamma tgammal;
+alias __builtin_ceil ceill;
+alias __builtin_floor floorl;
+alias __builtin_nearbyint nearbyintl;
+alias __builtin_rint rintl;
+alias __builtin_lrint lrintl;
+alias __builtin_llrint llrintl;
+alias __builtin_round roundl;
+alias __builtin_lround lroundl;
+alias __builtin_llround llroundl;
+alias __builtin_trunc truncl;
+alias __builtin_fmod fmodl;
+alias __builtin_remainder remainderl;
+alias __builtin_remquo remquol;
+alias __builtin_copysign copysignl;
+//alias __builtin_nan nanl;
+real nan(in char *);
+alias nan nanl;
+alias __builtin_nextafter nextafterl;
+alias __builtin_nextafter nexttowardl;
+alias __builtin_fdim fdiml;
+alias __builtin_fmax fmaxl;
+alias __builtin_fmin fminl;
+alias __builtin_fmal fmal;
+
+alias __builtin_sqrt sqrt;
+//alias __builtin_sqrtf sqrtf;//noldfuncs
+}

d/druntime/config/nosqrtf

+alias __builtin_sqrt sqrtf;

d/druntime/config/sqrtf

+alias __builtin_sqrtf sqrtf;

d/druntime/config/unix.x3

+x3_out_text(""
+    "module gcc.config.unix;\n"
+    "private import gcc.config.config;\n");
+
+x3_gi_push_header("\"config.h\"");
+x3_gi_push_header("<sys/types.h>"); // pretty much need this..
+
+int pop_count = 0;
+X3_Int dummy_int;
+X3_Type dummy_type;
+
+
+x3_gi_push_header("<dirent.h>");
+x3_gi_push_header("<sys/types.h>");
+x3_out_struct("struct dirent", NULL, "c:d_name", "o:d_type", NULL);
+x3_out_type_ex("DIR", NULL, "void");
+
+x3_push_optional(1);
+x3_out_enum(NULL, NULL, "^DT_[^_].*", NULL);
+x3_pop_optional();
+
+x3_gi_pop_headers(2);
+
+x3_gi_push_header("<unistd.h>");
+
+x3_gi_push_header("<limits.h>");
+x3_out_int_value("PATH_MAX");
+x3_gi_pop_header();
+
+x3_gi_push_header("<sys/types.h>");
+{
+    if (! x3_query_int_value("NFDBITS", "int", & dummy_int, & dummy_type)) {
+        /* for AIX */
+        ++pop_count;
+        x3_gi_push_header("<sys/select.h>");
+    }
+    x3_out_int_value("NFDBITS");
+    x3_out_int_value("FD_SETSIZE");
+
+    //x3_out_int_value_ex("__FD_SET_SIZEOF", "sizeof(fd_set)", "int", "int", 0);
+    x3_out_type("fd_set");
+    x3_out_int_type("mode_t");
+    x3_out_int_type("pid_t");
+    x3_out_int_type("uid_t");
+    x3_out_int_type("gid_t");
+    x3_out_int_type("off_t");
+    x3_out_int_type("ssize_t");
+}
+x3_gi_pop_headers(pop_count);
+
+x3_gi_push_header("<fcntl.h>");
+x3_out_enum(NULL, NULL, "^O_[^_].*", NULL);
+x3_out_enum(NULL, NULL, "^F_[^_].*", "-^F_OK$", NULL);
+x3_out_enum(NULL, NULL, "^[FWRX]_OK$", NULL);
+x3_gi_pop_header();
+
+{
+    x3_gi_push_header("<time.h>");
+
+    pop_count = 0;
+    x3_gi_push_header("<sys/time.h>");
+    if (x3_compile_test())
+        ++pop_count;
+    else
+        x3_gi_pop_header();
+
+    x3_gi_push_header("<sys/time.h>");
+
+    x3_out_struct("struct timespec", NULL, "i:tv_sec", "i:tv_nsec", NULL);
+    x3_out_struct("struct timeval", NULL, "i:tv_sec", "i:tv_usec", NULL);
+    x3_out_struct("struct timezone", "struct_timezone", "i:tz_minuteswest", "i:tz_dsttime", NULL);
+    x3_out_type_ex("clockid_t",NULL, "int");
+
+    x3_gi_pop_headers(pop_count); // sys/time.h
+    x3_gi_pop_header();
+}
+
+x3_gi_push_header("<utime.h>");
+x3_out_struct("struct utimbuf", NULL, "i:actime", "i:modtime", NULL);
+x3_gi_pop_header();
+
+x3_gi_push_header("<sys/stat.h>");
+x3_out_enum(NULL, NULL, "^S_I.*", NULL);
+x3_out_struct("struct stat", "struct_stat", "i:st_dev", "i:st_ino",
+    "i:st_mode", "i:st_nlink", "i:st_uid", "i:st_gid", "i:st_rdev",
+    "i:st_size", "i:st_blksize", "i:st_blocks", "i:st_atime", "i:st_mtime",
+    "i:st_ctime", NULL);
+x3_gi_pop_header();
+
+x3_gi_push_header("<signal.h>");
+x3_out_enum(NULL, NULL, "^SIG[^_].*", "-^SIGRT.*", NULL);
+x3_out_enum(NULL, NULL, "^SA_[^_].*", NULL);
+x3_out_type("sigset_t");
+x3_out_text("alias extern(C) void function(int) __sighandler_t;\n");
+{
+    static const char * nm[3] = {"SIG_DFL","SIG_IGN","SIG_ERR"};
+    int i;
+    for (i = 0; i < 3; i++) {
+        x3_out_int_value_ex(nm[i], nm[i], "void *", "__sighandler_t", 1, NULL);
+    }
+}
+
+x3_out_struct_ex("siginfo_t", NULL, 1, "i:si_signo", "i:si_errno", "i:si_code", NULL);
+
+{
+    X3_Struct * s = x3_struct_new_c_name("struct sigaction");
+    X3_Field * f;
+
+    s->struct_type.out_name = "sigaction_t";
+
+    f = x3_struct_new_field(s);
+    f->c_name = f->out_name = "sa_handler";
+    f->field_type.kind = X3_TYPE_KIND_NAME;
+    f->field_type.out_name = "extern(C) void function(int)";
+
+    f = x3_struct_new_field(s);
+    f->c_name = f->out_name = "sa_sigaction";
+    f->field_type.kind = X3_TYPE_KIND_NAME;
+    f->field_type.out_name = "extern(C) void function(int, siginfo_t *, void *)";
+
+    f = x3_struct_new_field(s);
+    f->c_name = f->out_name = "sa_mask";
+    f->field_type.kind = X3_TYPE_KIND_NAME;
+    f->field_type.out_name = "sigset_t";
+
+    f = x3_struct_new_field(s);
+    f->c_name = f->out_name = "sa_flags";
+    f->flags |= X3_FLAG_INT_TYPE;
+
+    x3_struct_finish(s);
+    x3_struct_out(s);
+}
+x3_gi_pop_header();
+
+//if (x3_query_cpp_if("HAVE_SYS_MMAN"))// why bother?
+x3_gi_push_header("<sys/mman.h>");
+if (x3_compile_test()) {
+    // need a new fuc for expl cast... MAP_FAILED
+    //x3_gi_push_optional(1);//? instead of optoelvl?
+    x3_out_int_value_ex("MAP_FAILED", NULL, "void *", NULL, 1, NULL);
+    x3_out_enum(NULL, NULL, "^PROT_[^_].*", NULL);
+    x3_out_enum(NULL, NULL, "^MAP_[^_].*", "-^MAP_FAILED$", NULL);
+    if (! x3_query_int_value("MAP_ANONYMOUS", "int", & dummy_int, & dummy_type))
+        x3_out_int_value_ex("MAP_ANONYMOUS", "MAP_ANON", "int", "int", 0, NULL);
+    if (! x3_query_int_value("MAP_ANON", "int", & dummy_int, & dummy_type))
+        x3_out_int_value_ex("MAP_ANON", "MAP_ANONYMOUS", "int", "int", 0, NULL);
+
+    x3_push_optional(1);
+    x3_out_enum(NULL, NULL, "^MS_[^_].*", NULL);
+    x3_out_enum(NULL, NULL, "^MCL_[^_].*", NULL);
+    x3_out_enum(NULL, NULL, "^MREMAP_[^_].*", NULL);
+    x3_out_enum(NULL, NULL, "^MADV_[^_].*", NULL);
+    x3_out_enum(NULL, NULL, "^MINCORE_[^_].*", NULL);
+    x3_pop_optional();
+
+}
+x3_gi_pop_header();
+
+x3_gi_push_header("<semaphore.h>");
+if (x3_compile_test())
+    x3_out_type("sem_t");
+x3_gi_pop_header();
+
+x3_gi_push_header("<pthread.h>");
+if (x3_compile_test())
+{
+    x3_out_type("pthread_t");
+    x3_out_type("pthread_attr_t");
+    x3_out_type("pthread_cond_t");
+    x3_out_type("pthread_condattr_t");
+    x3_out_type("pthread_mutex_t");
+    x3_out_type("pthread_mutexattr_t");
+    // other fields?
+    x3_out_struct("struct sched_param", NULL, "i:sched_priority", NULL);
+    //x3_push_optional(1);
+    x3_out_type_ex("pthread_barrier_t", NULL, X3_STRUCT_FALLBACK);
+    x3_out_type_ex("pthread_barrierattr_t", NULL, X3_STRUCT_FALLBACK);
+    x3_out_type_ex("pthread_rwlock_t", NULL, X3_STRUCT_FALLBACK);
+    x3_out_type_ex("pthread_rwlockattr_t", NULL, X3_STRUCT_FALLBACK);
+    x3_out_type_ex("pthread_spinlock_t", NULL, X3_STRUCT_FALLBACK);
+    //x3_pop_optional();
+    x3_out_enum(NULL, NULL, "^PTHREAD_CANCEL_.*", NULL);
+
+}
+x3_gi_pop_header();
+
+x3_gi_push_header("<sys/socket.h>");
+x3_gi_push_header("<netinet/in.h>");
+x3_gi_push_header("<netinet/tcp.h>");
+
+pop_count = 0;
+x3_gi_push_header("<netinet6/in6.h>");
+if (x3_compile_test())
+    pop_count = 1;
+else
+    x3_gi_pop_header();
+
+x3_gi_push_header("<netdb.h>");
+
+x3_out_type_ex("socklen_t", NULL, "int"); // uint?
+x3_out_enum(NULL, NULL, "^SOL_[^_].*", NULL);
+x3_out_enum(NULL, NULL, "^SO_[^_].*", NULL);
+x3_out_enum(NULL, NULL, "^SOCK_[^_].*", NULL);
+x3_out_enum(NULL, NULL, "^MSG_[^_].*", NULL);
+x3_out_text("static if (!is(typeof(MSG_NOSIGNAL))) enum { MSG_NOSIGNAL = 0 } // for std/socket.d\n");
+x3_gi_push_default_enum("AF_UNSPEC", "AF_IPX", "AF_APPLETALK", "AF_INET6", NULL);
+x3_out_enum(NULL, NULL, "^AF_[^_].*", NULL);
+x3_gi_pop_items(1);
+x3_gi_push_default_enum("PF_UNSPEC", "PF_IPX", "PF_APPLETALK", "PF_INET6", NULL);
+x3_out_enum(NULL, NULL, "^PF_[^_].*", NULL);
+x3_gi_pop_items(1);
+x3_out_struct("struct linger", NULL, "i:l_onoff", "i:l_linger", NULL);
+
+x3_gi_push_default_enum("3", "IPPROTO_GGP", NULL);
+x3_gi_push_default_enum("-1", "IPPROTO_IPV6", NULL);
+x3_out_enum(NULL, NULL, "^IPPROTO_.*", NULL);
+x3_gi_pop_items(2);
+
+x3_gi_push_default_enum("0",
+    "IPV6_UNICAST_HOPS", "IPV6_MULTICAST_IF", "IPV6_MULTICAST_HOPS",
+    "IPV6_MULTICAST_LOOP", "IPV6_JOIN_GROUP", "IPV6_LEAVE_GROUP", NULL);
+x3_out_enum(NULL, NULL, "^IPV6_.*", NULL);
+x3_gi_pop_items(1);
+
+x3_out_enum(NULL, "uint", "^INADDR_.*", NULL);
+x3_out_text("enum { ADDR_ANY = INADDR_ANY }\n"); // why does Phobos need this?
+x3_out_enum(NULL, NULL, "^TCP_.*", NULL);
+// or push text ifndef...
+//x3_out_enum("f-1;:", NULL,
+
+x3_out_struct("struct in_addr", NULL, "i:s_addr", NULL);
+x3_out_struct("struct sockaddr", NULL, "oib:sa_len", "ib:sa_family", "ob:sa_data", NULL);
+
+{
+    X3_Struct * s = x3_struct_new_c_name("struct sockaddr_in");
+    X3_Field * f;
+
+    f = x3_struct_new_field(s);
+    f->c_name = f->out_name = "sin_len";
+    f->flags = X3_FLAG_OPTIONAL|X3_FLAG_INT_TYPE|X3_FLAG_USE_BYTE;
+    f->init_expr = "sockaddr_in.sizeof";
+
+    f = x3_struct_new_field(s);
+    f->c_name = f->out_name = "sin_family";
+    f->flags = X3_FLAG_INT_TYPE|X3_FLAG_USE_BYTE;
+    f->init_expr = "AF_INET";
+
+    x3_struct_add_fields(s, "i:sin_port", "ob:sin_zero", NULL);
+
+    f = x3_struct_new_field(s);
+    f->c_name = f->out_name = "sin_addr";
+    f->field_type.kind = X3_TYPE_KIND_NAME;
+    f->field_type.out_name = "in_addr";
+
+    x3_struct_finish(s);
+    x3_struct_out(s);
+}
+
+
+x3_out_struct("struct protoent", NULL, "p_name", "p_aliases", "i:p_proto", NULL);
+x3_out_struct("struct servent", NULL, "s_name", "s_aliases", "i:s_port", "s_proto", NULL);
+{
+    X3_Struct * s = x3_struct_new_c_name("struct hostent");
+    x3_struct_add_fields(s, "h_name", "h_aliases", "h_addrtype", "h_length",
+        "h_addr_list", NULL);
+    x3_struct_add_extra(s, "\n"
+        "  char* h_addr()\n"
+        "  {\n"
+        "      return h_addr_list[0];\n"
+        "  }\n");
+    x3_struct_out(s);
+}
+/*//not required for std/socket.d yet
+{
+    FieldInfo fi[8];
+    struct addrinfo rec;
+    INT_FIELD(fi[0], ai_flags);
+    INT_FIELD(fi[1], ai_family);
+    INT_FIELD(fi[2], ai_socktype);
+    INT_FIELD(fi[3], ai_protocol);
+    INT_FIELD(fi[4], ai_addrlen);
+    ADD_FIELD(fi[5], "sockaddr *", ai_addr);
+    ADD_FIELD(fi[6], "char *", ai_canonname);
+    ADD_FIELD(fi[7], "addrinfo *", ai_next);
+    finish_struct(fi, 8, "addrinfo");
+}
+*/
+x3_out_text("struct addrinfo { }\n");
+
+x3_gi_pop_headers(4);
+x3_gi_pop_headers(pop_count);
+
+x3_gi_push_header("<pwd.h>");
+x3_out_struct("struct passwd", NULL, "pw_name", "pw_passwd", "i:pw_uid", "i:pw_gid",
+    "pw_gecos", "pw_dir", "pw_shell",
+    "o:pw_change", "o:pw_class", "o:pw_expire", NULL);
+x3_gi_pop_header();
+
+x3_gi_push_header("<termios.h>");
+
+x3_out_int_type("cc_t");
+x3_out_int_type("speed_t");
+x3_out_int_type("tcflag_t");
+
+x3_out_int_value("NCCS");
+
+x3_out_enum(NULL, NULL, "^TC[IOS].*", NULL);
+
+x3_out_struct("struct termios", NULL,
+    "i:c_iflag", "i:c_oflag", "i:c_cflag", "i:c_lflag",
+    "oc:c_line", "c:c_cc",
+    "oi:c_ispeed", "oi:c_ospeed");
+x3_gi_pop_header();

d/druntime/config/x3

+#!/bin/sh
+
+base=`basename $1`
+src=$base.c
+exe=$base.exe
+
+echo '#include "x3.h"' > $src
+echo 'void x3_go() {' >> $src
+cat "$1" >> $src
+echo '}' >> $src
+
+shift
+
+if $CC_FOR_BUILD -g -o $exe $src config/x3.o config/x3main.o $BUILD_LIBIBERTY; then
+    echo "** x3: running ./$exe" "$@"
+    ./$exe -v -t tmp$base "$@"
+    result=$?
+else
+    result=1
+fi
+
+if test $result -eq 0; then
+    rm -f $exe $src
+fi
+
+exit $result

d/druntime/config/x3.c

+#include <string.h>
+#include <stdlib.h>
+#include <libiberty.h>
+#include <errno.h>
+
+/* TODO: need to use autoconf to figure out which header to
+   include for unlink -- but need to do it for the *build*
+   system.  Also, before linking disabled due to cross
+   compilation...  */
+
+extern int unlink(const char *fn);
+
+#include "x3.h"
+#include "xregex.h"
+
+#define x3_assert(cond) {if(cond){}else{x3_error("assert failed: %s:%d: %s", \
+                                 __FILE__,__LINE__,#cond);exit(1);}}
+
+#define x3_new(T) ((T*)malloc(sizeof(T)))
+#define x3_new0(T) ((T*)calloc(1, sizeof(T)))
+
+#define diag(x) fprintf(stderr, x);
+
+static void _x3_write_d_int(FILE * f, X3_Int value, X3_Type *type);
+static void _x3_write_d_int_2(FILE * f, X3_Int value, unsigned size, int is_signed);
+
+char *
+x3f(const char * fmt, ...)
+{
+    char * result = NULL;
+    va_list va;
+
+    va_start(va, fmt);
+    vasprintf(& result, fmt, va);
+
+    return result;
+}
+
+X3_Global * global;
+
+void
+x3_array_init(X3_Array *ma)
+{
+    memset(ma, 0, sizeof(*ma));
+}
+
+void
+x3_array_fini(X3_Array *ma)
+{
+    free(ma->data);
+    memset(ma, 0, sizeof(*ma));
+}
+
+void
+x3_array_push(X3_Array *ma, void *data)
+{
+    if (ma->length >= ma->alloc) {
+        if (ma->alloc)
+            ma->alloc *= 2;
+        else
+            ma->alloc = 4;
+        ma->data = realloc(ma->data, sizeof(void*) * ma->alloc);
+    }
+    ma->data[ma->length++] = data;
+}
+
+void
+x3_array_pop(X3_Array *ma, X3_Size count)
+{
+    if (count <= ma->length)
+        ma->length -= count;
+    else
+        ma->length = 0;
+}
+
+void*
+x3_array_first(X3_Array *ma)
+{
+    if (ma->length)
+        return ma->data[0];
+    else
+        return NULL;
+}
+
+void*
+x3_array_last(X3_Array *ma)
+{
+    if (ma->length)
+        return ma->data[ma->length - 1];
+    else
+        return NULL;
+}
+
+X3_Result *
+x3_result_new()
+{
+    X3_Result * r = x3_new(X3_Result);
+    x3_result_init(r);
+    return r;
+}
+
+void
+x3_result_init(X3_Result * r)
+{
+    memset(r, 0, sizeof(*r));
+}
+
+void
+x3_result_delete(X3_Result * r)
+{
+    if (! r)
+        return;
+    free(r->data);
+    r->data = NULL;
+    free(r);
+}
+
+int
+x3_result_read_from_file(X3_Result * r, const char *filename)
+{
+    FILE * f;
+    X3_Size f_size;
+    int result = 0;
+
+    free(r->data);
+    r->data = NULL;
+
+    f = fopen(filename, "rb");
+    if (! f) {
+        fprintf(stderr, "cannot open object file: %s: %s\n", filename, strerror(errno));
+        return 0;
+    }
+    fseek(f, 0, SEEK_END);
+    f_size = ftell(f);
+    fseek(f, 0, SEEK_SET);
+
+    r->data = (X3u8*) malloc(f_size);
+    r->length = f_size;
+    if (fread(r->data, 1, f_size, f) != f_size) {
+        fprintf(stderr, "failed to read object file: %s: %s\n", filename, strerror(errno));
+        goto cleanup;
+    }
+
+    result = 1;
+
+ cleanup:
+    fclose(f);
+    return result;
+}
+
+void
+x3_result_rewind(X3_Result * r)
+{
+    r->pos = 0;
+}
+
+void
+x3_result_skip(X3_Result * r, unsigned count)
+{
+    /* !! */
+    r->pos += count;
+}
+
+static inline X3sig
+x3_result_read_sig(X3_Result * r)
+{
+    X3sig sig;
+    sig = (r->data[r->pos])|(r->data[r->pos+1]<<8)|
+        (r->data[r->pos+2]<<16)|(r->data[r->pos+3]<<24);
+    r->pos += 4;
+    return sig;
+}
+static inline unsigned/*!!*/
+x3_result_read_u32(X3_Result * r)
+{
+    return x3_result_read_integer(r, 4, 0);
+}
+
+int
+x3_result_find_next(X3_Result * r, X3sig sig)
+{
+    /* assumes data in object file is aligned.. */
+    while (r->pos < r->length && (r->pos & 3))
+        ++r->pos;
+
+    while (r->pos < r->length) {
+        if (x3_result_read_sig(r) == X3_SIG_HEADER)
+            if (r->pos < r->length &&
+                x3_result_read_sig(r) == sig)
+                return 1;
+    }
+    return 0;
+}
+
+int
+x3_result_find_sig(X3_Result * r, X3sig sig)
+{
+    x3_result_rewind(r);
+    if (x3_result_find_next(r, sig))
+        return 1;
+    else {
+        x3_error("cannot find expected data in output");
+        return 0;
+    }
+}
+
+int
+x3_result_find_item(X3_Result * r, unsigned uid)
+{
+    x3_result_rewind(r);
+    while (x3_result_find_next(r, X3_SIG_ITEM))
+        if (x3_result_read_uint(r) == uid)
+            return 1;
+    return 0;
+}
+
+int
+x3_result_read_u8(X3_Result * r)
+{
+    if (r->pos < r->length)
+        return r->data[r->pos++];
+    x3_error("read beyond end of input");
+    return -1;
+}
+
+int
+x3_result_read_int(X3_Result * r)
+{
+    return x3_result_read_integer(r, global->target_info.sizeof_int, 1);
+}
+
+unsigned
+x3_result_read_uint(X3_Result * r)
+{
+    return x3_result_read_integer(r, global->target_info.sizeof_int, 0);
+}
+
+X3_TgtSize
+x3_result_read_size(X3_Result * r)
+{
+    return x3_result_read_integer(r, global->target_info.sizeof_size_type, 0);
+}
+
+X3_Int
+x3_result_read_integer(X3_Result * r, int size, int is_signed)
+{
+    X3_UInt result;
+    X3u8 * p = r->data + r->pos ;
+
+    if (! size)
+        return 0;
+
+    r->pos += size;
+    if (! r->target_info->is_big_endian)
+        p += size - 1;
+    if (is_signed && (*p & 0x80))
+        result = (X3_Int) -1;
+    else
+        result = 0;
+    if (r->target_info->is_big_endian)
+        while (size--)
+            result = (result << 8) | *p++;
+    else
+        while (size--)
+            result = (result << 8) | *p--;
+    return result;
+}
+
+X3_InputItem*
+x3_input_item_new()
+{
+    X3_InputItem * ii = x3_new0(X3_InputItem);
+    return ii;
+}
+
+static void
+_x3_input_item_text_write_func(X3_InputItem * ii , FILE * f)
+{
+    fputs(ii->input_text, f);
+    fputc('\n', f);
+}
+
+static void
+_x3_input_item_subst_text_write_func(X3_InputItem * ii , FILE * f)
+{
+    const char *p;
+    const char *text = ii->input_text;
+    while ( (p = strchr(text, '@')) ) {
+        fwrite(text, 1, p - text, f);
+        fprintf(f, "%d", ii->uid);
+        text = p + 1;
+    }
+    fputs(text, f);
+    fputc('\n', f);
+}
+
+X3_InputItem*
+x3_input_item_new_text(const char * text)
+{
+    X3_InputItem * ii = x3_new0(X3_InputItem);
+    ii->input_text = text;
+    ii->write_func = & _x3_input_item_text_write_func;
+    return ii;
+}
+
+X3_InputGroup *
+x3_input_group_new()
+{
+    X3_InputGroup * ig = x3_new(X3_Array);
+    x3_array_init(ig);
+    return ig;
+}
+
+X3_Global*
+x3_global_create()
+{
+    global = x3_new0(X3_Global);
+    x3_global_init(global);
+    return global;
+}
+
+void
+x3_global_init(X3_Global * global)
+{
+    /* needed for integer writing to work */
+    x3_assert(sizeof(X3_Int) >= 8); /* maybe not for 32-bit targets */
+    x3_assert(sizeof(int) >= 4);
+    x3_assert(sizeof(int) * 2 >= sizeof(X3_Int));
+
+    memset(global, 0, sizeof(*global));
+    x3_array_init(& global->gcc_command);
+
+    x3_array_init(& global->input_groups);
+
+    global->header_group = x3_input_group_new();
+    x3_array_push(& global->input_groups, global->header_group);
+
+    global->current_group = x3_input_group_new();
+    x3_array_push(& global->input_groups, global->current_group);
+
+    x3_array_init(& global->optional_stack);
+
+    global->log_stream = stderr;
+
+    x3_push_optional(0);
+
+}
+
+void
+x3_global_set_temp_fn_base(const char * temp_base)
+{
+    global->temp_base = temp_base;
+
+    char * log_fn = concat(global->temp_base, ".log", NULL);
+    if ( (global->log_stream = fopen(log_fn, "a")) != NULL )
+        global->log_path = log_fn;
+    else
+        free(log_fn);
+}
+
+char *
+x3_global_get_temp_fn(const char * suffix)
+{
+    // TODO: use make_temp_file..
+    if (global->temp_base) {
+        char buf[96];
+        snprintf(buf, sizeof(buf), "%s%s", global->temp_base, suffix);
+        return strdup(buf);
+    } else
+        return make_temp_file(suffix);
+}
+
+int
+x3_global_keep_temps()
+{
+    return global->temp_base != NULL;
+}
+
+
+void
+x3_push_optional(int optional)
+{
+    x3_array_push(& global->optional_stack, (void *) optional);
+}
+
+void
+x3_pop_optional()
+{
+    x3_array_pop(& global->optional_stack, 1);
+}
+
+int
+x3_is_optional()
+{
+    return x3_array_last(& global->optional_stack) != (void*) 0 ;
+}
+
+static void x3_logv(const char *fmt, va_list va)
+{
+    FILE * stream = stderr;
+
+    if (global)
+        stream = global->log_stream;
+
+    fputs("x3: ", stream);
+    vfprintf(stream, fmt, va);
+    fputc('\n', stream);
+}
+
+
+void x3_log(const char *fmt, ...)
+{
+    va_list va;
+    va_start(va, fmt);
+    x3_logv(fmt, va);
+    va_end(va);
+}
+
+void
+x3_error(const char *fmt, ...)
+{
+    va_list va, va2;
+
+    fputs("x3: ", stderr);
+    va_start(va, fmt);
+    va_copy(va2, va);
+    x3_logv(fmt, va2);
+    vfprintf(stderr, fmt, va);
+    if (global)
+        global->error_count++;
+    fputc('\n', stderr);
+    exit(1);
+}
+
+int
+x3_unsupported(const char * detail)
+{
+    x3_error("target unsupported: %s", detail);
+    return 0;
+}
+
+int
+x3_interp_error(const char * detail)
+{
+    x3_error("cannot interpret output: %s", detail);
+    return 0;
+}
+
+int
+x3_gcc_execute(X3_Array extra_args)
+{
+    int status;
+    const char * result;
+#if _WIN32
+    /* x3 programs get the c:\foo\bar form of path names.  Passing that
+       as a program name to the MSYS shell's 'exec' causes the path
+       to be mangled. */
+    const char * exec_bit = "\"$@\"";
+#else
+    const char * exec_bit = "exec \"$@\"";
+#endif
+    char * cmd = concat(exec_bit,
+        global->log_path ? " >>" : "",
+        global->log_path ? global->log_path : "", // TODO: assumptions about charaters in the path
+        global->log_path ? " 2>&1" : "",
+        NULL);
+
+    char**args = (char**)malloc(sizeof(char*) *
+        (global->gcc_command.length + extra_args.length + 4 + 1));
+    int argi = 0;
+    char * shell = getenv("SHELL");
+
+    if (! shell)
+        shell = "sh";
+
+    args[argi++] = shell;
+    args[argi++] = "-c";
+    args[argi++] = cmd;
+    args[argi++] = shell;
+
+    memcpy(args + argi, global->gcc_command.data,
+        global->gcc_command.length * sizeof(char*));
+    argi += global->gcc_command.length;
+
+    memcpy(args + argi, extra_args.data,
+        extra_args.length * sizeof(char*));
+    argi += extra_args.length;
+    args[argi++] = NULL;
+
+    FILE * stream = global->log_stream;
+    int i;
+    if (global->print_gcc_command) {
+        fprintf(stream, "x3: running gcc: ");
+        for (i = 0; args[i]; ++i)
+            fprintf(stream, "%s ", args[i]);
+        fprintf(stream, "\n");
+    }
+    fflush(stream);
+
+#ifdef PEX_RECORD_TIMES
+    {
+        int err;
+        result = pex_one(PEX_SEARCH, args[0], args, "x3", NULL, NULL, & status, & err);
+        if (! result) {
+            /*
+              if (status == 0)
+              return 1;
+              else { // TODO: signals fatal?
+              fprintf(stderr, "error: %s exited with %s %d\n",
+              args[0], status > 0 ? "code" : "signal",
+              status > 0 ? status : -status);
+              return 0;
+              }
+            */
+            return status == 0;
+        }
+    }
+#else
+    {
+        char * errmsg_arg;
+        char * rr;
+
+        int pid = pexecute(args[0], args, "x3", NULL,
+            & rr, & errmsg_arg, PEXECUTE_SEARCH | PEXECUTE_ONE);
+        result = rr;
+        if (pid > 0) { /* !! */
+            if (pwait(pid, & status, 0) != -1)
+                return status == 0;
+            else {
+                fprintf(stderr, "pwait failed: %s\n", strerror(errno));
+                return 0;
+            }
+        }
+    }
+#endif
+    free(cmd);
+
+    x3_error("failed to run compiler: %s", result);
+    return 0;
+}
+
+int
+x3_gcc_execute_l(const char * extra, ...)
+{
+    va_list va;
+    X3_Array extra_args;
+
+    va_start(va, extra);
+    x3_array_init(& extra_args);
+    x3_array_push(& extra_args, (/*!!*/ char *) extra);
+    while (1) {
+        char *p = va_arg(va, char *);
+        if (p)
+            x3_array_push(& extra_args, p);
+        else
+            break;
+    }
+    va_end(va);
+
+    return x3_gcc_execute(extra_args);
+}
+
+/* Run compiler using the current input data. Not an error if it fails. */
+int
+x3_compile_test(void)
+{
+    const char * src_fn = x3_global_get_temp_fn(".c");
+    const char * obj_fn = x3_global_get_temp_fn(".o");
+    FILE * f = fopen(src_fn, "w");
+    int result = 0;
+    int gcc_result;
+
+    x3_result_delete(global->result);
+    global->result = NULL;
+
+    /* TODO: errors */
+    x3_gi_write_to_FILE(f);
+    fclose(f);
+
+    gcc_result = x3_gcc_execute_l("-c", src_fn, "-o", obj_fn, NULL);
+    if (gcc_result) {
+        int i1, i2;
+
+        /* open blob... */
+        global->result = x3_result_new();
+        global->result->target_info = & global->target_info;
+        if (! x3_result_read_from_file(global->result, obj_fn))
+            /* TODO print error? */
+            goto cleanup;
+
+        for (i1 = 0; i1 < x3al(& global->input_groups); ++i1) {
+            X3_InputGroup * ig = x3ae(& global->input_groups, i1, X3_InputGroup *);
+            for (i2 = 0; i2 < x3al(ig); ++i2) {
+                X3_InputItem * ii = x3ae(ig, i2, X3_InputItem *);
+                if (ii->post_func)
+                    ii->post_func(ii, global->result);
+            }
+        }
+
+        result = 1;
+    }
+
+ cleanup:
+    if (! x3_global_keep_temps()) {
+        unlink(src_fn);
+        unlink(obj_fn);
+    }
+    return result;
+}
+
+char *
+_x3_read_line(FILE *f, char * buf, unsigned buf_size)
+{
+    char * p = fgets(buf, buf_size, f);
+    char * q;
+    if (! p)
+        return NULL;
+    while (! (q=strchr(p, '\n')) && ! feof(f)) {
+        size_t len = strlen(p);
+        if (p == buf) {
+            p = (char*) malloc(len * 2);
+            strncpy(p, buf, len);
+            p[len] = 0;
+        } else
+            p = (char*) realloc(p, len * 2);
+        fgets(p + len, len, f);
+    }
+    if (q)
+        *q = 0;
+    return p;
+}
+
+static regex_t *
+_x3_get_macros_regex() {
+    static int initialized = 0;
+    static regex_t macros_regex;
+    if (! initialized) {
+        initialized = 1;
+        if (regcomp(& macros_regex,
+                "^#define ([^[:space:]\(]+)(\\([^[:space:]]+\\))?([[:space:]](.*))?$",
+                REG_EXTENDED) != 0) {
+            x3_assert("failed to compile regex"==0);
+            return NULL;
+        }
+    }
+    return & macros_regex;
+}
+
+char *
+_x3_strdup_slice(const char * s, int start, int end)
+{
+    int len = end - start;
+    char * result = (char*) malloc(len + 1);
+    strncpy(result, s + start, len);
+    result[len] = '\0';
+    return result;
+}
+
+int
+x3_compile_get_macros(X3_Array * out_macros)
+{
+    const char * src_fn = x3_global_get_temp_fn(".c");
+    const char * mac_fn = x3_global_get_temp_fn(".macros");
+    FILE * f = fopen(src_fn, "w");
+    int result = 0;
+    int gcc_result;
+    regex_t * re = _x3_get_macros_regex();
+
+    /* TODO: errors */
+    x3_gi_write_to_FILE(f);
+    fclose(f);
+
+    if (! re)
+        return 0;
+
+    gcc_result = x3_gcc_execute_l("-E", "-dM", "-o", mac_fn, src_fn, NULL);
+    if (gcc_result) {
+        X3_Array macros;
+        char buf[1024];
+        char *line;
+
+        result = 0;
+        f = fopen(mac_fn, "r");
+        if (!f) {
+            x3_error("cannot open %s: %s", mac_fn, strerror(errno));
+            goto cleanup;
+        }
+
+        x3_array_init(& macros);
+
+        while ( (line = _x3_read_line(f, buf, sizeof(buf))) ) {
+            regmatch_t matches[4];
+            if (regexec(re, line, 4, matches, 0) == 0) {
+                X3_Macro * macro = x3_new0(X3_Macro);
+                macro->name = _x3_strdup_slice(line, matches[1].rm_so, matches[1].rm_eo);
+                macro->args = _x3_strdup_slice(line, matches[2].rm_so, matches[2].rm_eo);
+                macro->def = _x3_strdup_slice(line, matches[3].rm_so, matches[3].rm_eo);
+                /*fprintf(stderr, "{%s}{%s}{%s}\n", macro->name, macro->args, macro->def);*/
+                x3_array_push(& macros, macro);
+            }
+        }
+
+        *out_macros = macros;
+        result = 1;
+    }
+
+ cleanup:
+    if (! x3_global_keep_temps()) {
+        unlink(src_fn);
+        unlink(mac_fn);
+    }
+    return result;
+}
+
+/* Run GCC.  If it fails, it is an error. */
+int
+x3_compile(void)
+{
+    int result = x3_compile_test();
+    if (! result)
+        x3_error("error: compiler exited with error");
+    return result;
+}
+
+static const char * _x3_offsetof_function = "offsetof";
+
+void
+x3_gi_push_standard()
+{
+    x3_gi_push_text(x3f("typedef %s x3i_size_t;", global->target_info.size_type));
+
+    /* GCC 3.x does not have __builtin_offsetof... */
+    x3_gi_push_header("<stddef.h>");
+}
+
+void
+x3_gi_write_to_FILE(FILE *f)
+{
+    int i1, i2;
+    unsigned uid = 1;
+
+    for (i1 = 0; i1 < x3al(& global->input_groups); ++i1) {
+        X3_InputGroup * ig = x3ae(& global->input_groups, i1, X3_InputGroup *);
+        for (i2 = 0; i2 < x3al(ig); ++i2) {
+            X3_InputItem * ii = x3ae(ig, i2, X3_InputItem *);
+            ii->uid = uid++;
+            if (ii->write_func)
+                ii->write_func(ii, f);
+        }
+    }
+}
+
+
+void
+x3_gi_push_header(const char *hdr)
+{
+    X3_InputItem * ii = x3_input_item_new_text(x3f("#include %s\n", hdr));
+    x3_array_push(global->header_group, ii);
+}
+
+void
+x3_gi_push_headers_l(const char * hdr, ...)
+{
+    x3_gi_push_header(hdr);
+
+    va_list va;
+    va_start(va, hdr);
+    while (1) {
+        const char *p = va_arg(va, const char *);
+        if (p)
+            x3_gi_push_header(p);
+        else
+            break;
+    }
+    va_end(va);
+}
+
+void
+x3_gi_pop_header()
+{
+    x3_gi_pop_headers(1);
+}
+
+void
+x3_gi_pop_headers(int count)
+{
+    x3_array_pop(global->header_group, 1);
+}
+
+void
+x3_gi_push_group()
+{
+    global->current_group = x3_input_group_new();
+    x3_array_push(& global->input_groups, global->current_group);
+}
+
+void
+x3_gi_pop_group()
+{
+    x3_array_pop(& global->input_groups, 1);
+    global->current_group = x3_array_last(& global->input_groups);
+}
+
+void
+x3_gi_push_input_item(X3_InputItem *ii)
+{
+    x3_array_push(global->current_group, ii);
+}
+
+void
+x3_gi_pop_items(int count)
+{
+    x3_array_pop(global->current_group, count);
+}
+
+X3_InputItem*
+x3_gi_push_text(const char *text)
+{
+    X3_InputItem* ii = x3_input_item_new_text(text);
+    x3_gi_push_input_item(ii);
+    return ii;
+}
+
+X3_InputItem*
+x3_gi_push_subst_text(const char *text)
+{
+    X3_InputItem* ii = x3_input_item_new_text(text);
+    ii->write_func = & _x3_input_item_subst_text_write_func;
+    x3_gi_push_input_item(ii);
+    return ii;
+}
+
+
+static void
+_x3_input_int_value_write_func(X3_InputItem * xi , FILE * f)
+{
+    X3_InputIntValue * ii = (X3_InputIntValue *) xi;
+    unsigned uid = ii->iit.ii.uid;
+    const char *type_name = ii->iit.type_name;
+    x3_gi_write_start_item(f, uid);
+    fprintf(f, "x3i_size_t int_sz; int int_sgn; %s int_val;\n", type_name);
+    x3_gi_write_start_item_data(f, uid);
+    fprintf(f, "sizeof(%s), ((%s)-1)<0, %s", type_name, type_name,
+        ii->iit.ii.input_text);
+    x3_gi_write_finish_item(f);
+}
+
+static void
+_x3_input_int_value_post_func(X3_InputItem * xi , X3_Result * result)
+{
+    X3_InputIntValue * ii = (X3_InputIntValue *) xi;
+    if (x3_result_find_item(result, ii->iit.ii.uid)) {
+        int sz = x3_result_read_size(result);
+        int sgn = x3_result_read_int(result);
+        ii->iit.int_type_size = sz;
+        ii->iit.int_type_is_signed = sgn;
+        ii->int_value = x3_result_read_integer(result, sz, sgn);
+    }
+    /* !! find_item doesn't record error ... do it here? */
+}
+
+X3_InputIntValue*
+x3_gi_push_int_value(const char *expr)
+{
+    X3_InputIntValue * ii = x3_new0(X3_InputIntValue);
+    ii->iit.ii.write_func = & _x3_input_int_value_write_func;
+    ii->iit.ii.post_func = & _x3_input_int_value_post_func;
+    ii->iit.type_name = "int";
+    ii->iit.ii.input_text = expr;
+    x3_gi_push_input_item(& ii->iit.ii);
+    return ii;
+}
+
+
+void
+x3_gi_push_default_enum(const char * default_val, ...)
+{
+    va_list va;
+    char * result = "";
+
+    va_start(va, default_val);
+    while (1) {
+        const char * p = va_arg(va, const char *);
+        if (! p)
+            break;
+        result = x3f("%s"
+            "#ifndef %s\n# define %s %s\n#endif\n",
+            result, p, p, default_val);
+    }
+    x3_gi_push_text(result);
+}
+
+void
+x3_gi_write_start_item(FILE *f, unsigned uid)
+{
+    fprintf(f, "struct { char _x3_sig[4]; char _x3_type[4]; unsigned _x3_uid;\n  ");
+}
+
+void
+x3_gi_write_start_item_data(FILE *f, unsigned uid)
+{
+    fprintf(f, "} __attribute__((packed)) \n_x3_item_%d\n = { \"zOmG\", \"iTeM\", %d, ",
+        uid, uid);
+}
+
+void
+x3_gi_write_finish_item(FILE *f)
+{
+    fprintf(f, "};\n");
+}
+
+int
+x3_query_target_info(X3_TargetInfo *ti)
+{
+    int v;
+    int sz[5];
+    int result = 0;
+    int ok;
+
+    x3_gi_push_group();
+
+    x3_gi_push_text("struct { char sig[4]; char what[4];"
+        "unsigned char sz_char; unsigned char sz_short; "
+        "unsigned char sz_int; unsigned char sz_long_long; "
+        "unsigned char sz_long; unsigned short endian_test; }\n "
+        "__attribute__((packed)) _x3i_tgt_info = {\n"
+        "\"zOmG\", \"tGtI\", sizeof(char), sizeof(short), "
+        "sizeof(int), sizeof(long long), sizeof(long), "
+        "0x2211 };\n");
+    if (! x3_compile())
+        goto cleanup;
+
+    if (! x3_result_find_sig(global->result, X3_SIG('t','G','t','I')))
+        goto cleanup;
+
+    sz[0] = ti->sizeof_char = x3_result_read_u8(global->result);
+    if (ti->sizeof_char != 1) {
+        x3_unsupported("sizeof(char) is not 1");
+        goto cleanup;
+    }
+    sz[1] = ti->sizeof_short = x3_result_read_u8(global->result);
+    sz[2] = ti->sizeof_int = x3_result_read_u8(global->result);
+    sz[3] = ti->sizeof_long_long = x3_result_read_u8(global->result);
+    sz[4] = ti->sizeof_long = x3_result_read_u8(global->result);
+    v = x3_result_read_u8(global->result);
+    if (v == 0x11)
+        ti->is_big_endian = 0;
+    else {
+        x3_result_skip(global->result, ti->sizeof_short - 2);
+        if (x3_result_read_u8(global->result) != 0x11)
+            x3_interp_error("cannot determine byte order");
+        ti->is_big_endian = 1;
+    }
+
+    x3_gi_push_header("<sys/types.h>");
+    x3_gi_pop_items(1);
+    x3_gi_push_text("struct { char sig[4]; char what[4];"
+        "unsigned char sz_szt; }\n "
+        "__attribute__((packed)) _x3i_szt_info = {\n"
+        "\"zOmG\", \"tGtI\", sizeof(size_t) };\n");
+    ok = x3_compile();
+    x3_gi_pop_headers(1);
+    ti->size_type = "unsigned int";
+    ti->sizeof_size_type = ti->sizeof_int;
+
+    result = 1;
+
+ cleanup:
+    x3_gi_pop_group();
+    return result;
+}
+
+int
+x3_query_int_type(const char *name, X3_Type * type)
+{
+    X3_Int dummy;
+    return x3_query_int_value("0", name, & dummy, type);
+}
+
+int
+x3_query_type(const char *name, X3_Type * type)
+{
+    static unsigned uid_counter = 1;
+    X3_Int  int_val;
+    X3_Type dummy;
+    char * p;
+    unsigned my_uid = ++uid_counter;
+
+    type->ok = 0;
+
+    x3_gi_push_group();
+
+    /* test if type is even valid */
+    const char * td_name = x3f("_x3i_qttd_%d", my_uid);
+    x3_gi_push_text(p = x3f("typedef %s %s;\n", name, td_name));
+    if (! x3_compile_test())
+        goto cleanup;
+
+    /* is it just void? */
+    if (x3_query_int_value(x3f("__builtin_types_compatible_p(void,%s)", name),
+            "int", & int_val, & dummy) && int_val) {
+        type->ok = 1;
+        type->kind = X3_TYPE_KIND_VOID;
+    } else {
+        if (! x3_query_int_value(x3f("sizeof(%s)", name), "x3i_size_t", & int_val, & dummy))
+            goto cleanup;
+        type->type_size = (X3_UInt) int_val;
+
+        /* test if scalarish (or array...) */
+        int result1;
+        x3_gi_push_subst_text(x3f("\n"
+                "const %s  _x3i_qt_@_1;\n"
+                "typedef typeof(_x3i_qt_@_1 < 0) _x3i_qt_@_2;", name));
+        result1 = x3_compile_test();
+        x3_gi_pop_items(1);
+        if (result1) {
+            int result2;
+            /* is it a pointer or array? */
+            const char * sub_td_name = x3f("_x3i_qttd_%d_sub", my_uid);
+            x3_gi_push_subst_text(p = x3f("\n"
+                    "const %s  _x3i_qt_inst_@;\n"
+                    "typedef typeof(* _x3i_qt_inst_@) %s;", name, sub_td_name));
+            result2 = x3_compile_test();
+            if (result2) {
+
+                if (x3_query_int_value(x3f(""
+                            "__builtin_types_compatible_p(%s[],%s)",
+                            sub_td_name, td_name),
+                        "int", & int_val, & dummy) && int_val) {
+                    /* It is an array type. */
+                    type->kind = X3_TYPE_KIND_ARRAY;
+                    type->next = x3_type_new();
+                    type->next->flags |= type->flags & (X3_FLAG_USE_CHAR|X3_FLAG_USE_BYTE);
+                    if (! x3_query_type(sub_td_name, type->next))
+                        goto cleanup;
+                    if (type->type_size && type->next->type_size) {
+                        x3_assert( (type->type_size % type->next->type_size) == 0);
+                        type->u.array_length = type->type_size / type->next->type_size;
+                    } else
+                        type->u.array_length = 0;
+                    type->next->out_name = NULL;
+                    type->ok = 1;
+
+                } else { /* It is pointer. */
+                    int is_ptr_to_func = 0;
+
+                    type->kind = X3_TYPE_KIND_POINTER;
+                    type->next = x3_type_new();
+
+                    /* Test for pointer to function which can do *type forever... */
+                    x3_gi_push_subst_text(x3f("\n"
+                            "const %s _x3i_qtptf_@;\n"
+                            "typedef typeof(*_x3i_qtptf_@) _x3i_qtptf_f2_%d;\n",
+                            sub_td_name, my_uid));
+                    is_ptr_to_func =  x3_query_int_value(x3f("\n"
+                            "__builtin_types_compatible_p(%s,_x3i_qtptf_f2_%d)",
+                            sub_td_name, my_uid),
+                        "int", & int_val, & dummy) && int_val;
+                    x3_gi_pop_items(1);
+                    if (! is_ptr_to_func)
+                        x3_query_type(sub_td_name, type->next);
+                    if (! type->next->ok || type->next->kind == X3_TYPE_KIND_RECORD) {
+                        /* void* is good enough... */
+                        type->next->ok = 1;
+                        type->next->kind = X3_TYPE_KIND_VOID;
+                        type->next->c_name = type->next->out_name = "void";
+                    }
+                    type->next->out_name = NULL;
+                    type->ok = 1;
+                }
+                x3_gi_pop_items(1);
+            } else {
+                x3_gi_pop_items(1);
+                /* Must be an int */
+                x3_query_int_type(name, type);
+                type->out_name = NULL;
+            }
+        } else {
+            /* if we get a pointer to this, there's gonna be a problem...
+               array and pointer above need to check this and either push
+               a private type or change it to an array of bytes... !!
+
+               also a problem if an instance...
+            */
+
+            X3_Struct * s = x3_struct_new();
+            X3_Field * f;
+
+            f = x3_struct_new_field(s);
+            f->ok = 1;
+            f->out_name = "__opaque";
+            f->field_type.ok = 1;
+            f->field_type.kind = X3_TYPE_KIND_NAME;
+            f->field_type.type_size = type->type_size;
+            f->field_type.out_name = x3f("byte[%u]", (unsigned) type->type_size);
+            /* might be function (not ptr-to-functiono) or struct... keep it as a name.. */
+            /* !! figure out alignment... */
+            type->ok = 1;
+            type->kind = X3_TYPE_KIND_RECORD;
+            type->u.struct_def = s;
+
+            s->finished = 1;
+            s->struct_type = *type;
+        }
+    }
+
+ cleanup:
+    --uid_counter;
+    x3_gi_pop_group();
+    return type->ok;
+}
+
+int
+x3_query_int_value(const char *expr, const char *type_name,
+    X3_Int * out_value, X3_Type * out_type)
+{
+    x3_assert(type_name != NULL);
+    X3_InputIntValue *c = x3_gi_push_int_value(expr);
+    c->iit.type_name = type_name;
+    if (x3_compile_test()) {
+        out_type->ok = 1;
+        out_type->kind = X3_TYPE_KIND_INT;
+        out_type->c_name = type_name;
+        if (! out_type->out_name)
+            out_type->out_name = type_name;
+        out_type->type_size = c->iit.int_type_size;
+        out_type->type_is_signed = c->iit.int_type_is_signed;
+        *out_value = c->int_value;
+    } else
+        out_type->ok = 0;
+    x3_gi_pop_items(1);
+    return out_type->ok;
+}
+
+
+static const char *
+_x3_d_int_type(X3_Type * type)
+{
+    x3_assert(type->kind == X3_TYPE_KIND_INT);
+    switch (type->type_size) {
+    case 1:
+        if (type->flags & X3_FLAG_USE_BYTE)
+            return type->type_is_signed ? "byte" : "ubyte";
+        else
+            return "char";
+    case 2: return type->type_is_signed ? "short" : "ushort";
+    case 4: return type->type_is_signed ? "int" : "uint";
+    case 8: return type->type_is_signed ? "long" : "ulong";
+    default:
+        x3_error("no D equivalent for integer type of %d bytes", (int) type->type_size);
+        return "error";
+    }
+}
+
+static const char *
+_x3_d_char_type(X3_Type * type)
+{
+    x3_assert(type->kind == X3_TYPE_KIND_INT);
+    switch (type->type_size) {
+    case 1: return "char";
+    case 2: return "wchar";
+    case 4: return "dchar";
+    default:
+        x3_error("no D character type of %d bytes", (int) type->type_size);
+        return "error";
+    }
+}
+
+static void
+_x3_write_d_int_2(FILE * f, X3_Int value, unsigned size, int is_signed)
+{
+    if (is_signed) {
+        int hi = (value >> (int)32) & 0xffffffff;
+        if (hi == 0 || hi == -1)
+            fprintf(f, "%d", (int)value);
+        else
+            /* !! grr.... */
+            fprintf(f, "cast(long)0x%x%08x", hi, (unsigned)(value & 0xffffffff));
+    } else {
+        unsigned hi = ((X3_UInt) value >> (unsigned)32) & 0xffffffff;
+        if (hi == 0)
+            fprintf(f, "%u", (unsigned)value);
+        else
+            fprintf(f, "0x%x%08xUL", hi, (unsigned)(value & 0xffffffff));
+    }
+}
+
+static void
+_x3_write_d_int(FILE * f, X3_Int value, X3_Type *type)
+{
+    x3_assert(type->kind == X3_TYPE_KIND_INT);
+    _x3_write_d_int_2(f, value, type->type_size, type->type_is_signed);
+}
+
+static const char * _x3_format_d_type(X3_Type *type);
+
+static const char *
+_x3_format_d_type_ex(X3_Type *type, int use_name)
+{
+    const char * result;
+    x3_assert(type->ok);
+    if (! type->out_name || ! use_name) {
+        switch (type->kind)
+        {
+        case X3_TYPE_KIND_VOID:
+            result = "void";
+            break;
+        case X3_TYPE_KIND_INT:
+            result = _x3_d_int_type(type);
+            break;
+        case X3_TYPE_KIND_ARRAY:
+            result = x3f("%s[%u]", _x3_format_d_type(type->next),
+                (unsigned) type->u.array_length);
+            break;
+        case X3_TYPE_KIND_POINTER:
+            result = x3f("%s*", _x3_format_d_type(type->next));
+            break;
+        default:
+            x3_assert(0);
+        }
+        /*
+        if (! type->out_name && use_name)
+        type->out_name = result !! // ...should be separate cached.
+        */
+    } else
+        result = type->out_name;
+    return result;;
+}
+
+static const char *
+_x3_format_d_type(X3_Type *type)
+{
+    return _x3_format_d_type_ex(type, 1);
+}
+
+
+X3_Type *
+x3_type_new(void)
+{
+    X3_Type * t = x3_new0(X3_Type);
+    x3_type_init(t);
+    return t;
+}
+
+void
+x3_type_init(X3_Type * type)
+{
+    memset(type, 0, sizeof(*type));
+    type->flags |= X3_FLAG_USE_CHAR;
+}
+
+void
+x3_type_out(X3_Type * type)
+{
+    x3_assert(type->ok);
+
+    const char * out_name = type->out_name ? type->out_name : type->c_name;
+    if (! out_name)
+        return; // !!?
+
+    switch (type->kind)
+    {
+    case X3_TYPE_KIND_NAME:
+        // can't do anything !!?
+        break;
+    case X3_TYPE_KIND_RECORD:
+        x3_struct_out(type->u.struct_def);
+        break;
+    case X3_TYPE_KIND_ERROR:
+        // !!
+        break;
+    default:
+        fprintf(global->output_stream, "alias %s %s;\n",