diff -uNrp dmd-1.004/src/dmd/aggregate.h gdc-0.22/d/dmd/aggregate.h --- dmd-1.004/src/dmd/aggregate.h 2007-01-26 15:53:22.000000000 +0100 +++ gdc-0.22/d/dmd/aggregate.h 2007-02-03 17:34:12.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + #ifndef DMD_AGGREGATE_H #define DMD_AGGREGATE_H @@ -56,6 +62,7 @@ struct AggregateDeclaration : ScopeDsymb NewDeclaration *aggNew; // allocator DeleteDeclaration *aggDelete; // deallocator + Expressions * attributes; // GCC decl/type attributes #ifdef IN_GCC Array methods; // flat list of all methods for debug information #endif diff -uNrp dmd-1.004/src/dmd/attrib.c gdc-0.22/d/dmd/attrib.c --- dmd-1.004/src/dmd/attrib.c 2007-01-24 16:25:02.000000000 +0100 +++ gdc-0.22/d/dmd/attrib.c 2007-02-03 17:34:12.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + #include #include #include @@ -745,6 +751,7 @@ Dsymbol *PragmaDeclaration::syntaxCopy(D void PragmaDeclaration::semantic(Scope *sc) { // Should be merged with PragmaStatement + Scope sc_save; //printf("\tPragmaDeclaration::semantic '%s'\n",toChars()); if (ident == Id::msg) @@ -811,13 +818,133 @@ void PragmaDeclaration::semantic(Scope * if (e->op == TOKstring && ((StringExp *)e)->sz == 1) s = ((StringExp *)e); else - error("second argument of GNU_asm must be a char string"); + error("second argument of GNU_asm must be a character string"); if (d && s) d->c_ident = Lexer::idPool((char*) s->string); } goto Lnodecl; } + else if (ident == Id::GNU_attribute) + { + sc_save = *sc; + + // An empty list is allowed. + if (args && args->dim) + { + Expressions * a; + + if (sc->attributes) + a = (Expressions *) sc->attributes->copy(); + else + a = new Expressions; + sc->attributes = a; + + for (unsigned i = 0; i < args->dim; i++) + { + Expression * e = (Expression *) args->data[i]; + //e = e->semantic(sc); + + if (e->op == TOKidentifier) { + /* ok */ + } else if (e->op == TOKcall) { + CallExp * c = (CallExp *) e; + if (c->e1->op != TOKidentifier) + error("identifier or call expression expected for attribute"); + if (c->arguments) + for (int unsigned ai = 0; ai < c->arguments->dim; ai++) + { + c->arguments->data[ai] = + ((Expression *) c->arguments->data[ai])->semantic(sc); + } + } + else + { + error("identifier or call expression expected for attribute"); + continue; + } + a->push(e); + } + } + } + else if (ident == Id::GNU_set_attribute) + { + if (!args || args->dim < 1) + error("declaration expected for setting attributes"); + else + { + Array p_attributes_list; // of Expressions** + { + Expression * e = (Expression *) args->data[0]; + Expressions ** pa = NULL; + + e = e->semantic(sc); + if (e->op == TOKvar) + { + Declaration * d = ((VarExp *)e)->var; + if (d->isFuncDeclaration() || d->isVarDeclaration()) + pa = & d->attributes; + } + else if (e->op == TOKtype) + { + Type * t = ((TypeExp *)e)->type; + if (t->ty == Ttypedef) + pa = & ((TypeTypedef *) t)->sym->attributes; + else if (t->ty == Tenum) + pa = & ((TypeEnum *) t)->sym->attributes; + else if (t->ty == Tstruct) + pa = & ((TypeStruct *) t)->sym->attributes; + else if (t->ty == Tclass) + pa = & ((TypeClass *) t)->sym->attributes; + } + + if (pa) + p_attributes_list.push(pa); + else + error("first argument must be a function, variable, or type declaration"); + } + + Expressions * new_attrs = new Expressions; + for (unsigned i = 1; i < args->dim; i++) + { + Expression * e = (Expression *) args->data[i]; + //e = e->semantic(sc); + + if (e->op == TOKidentifier) { + /* ok */ + } else if (e->op == TOKcall) { + CallExp * c = (CallExp *) e; + if (c->e1->op != TOKidentifier) + error("identifier or call expression expected for attribute"); + if (c->arguments) + for (int unsigned ai = 0; ai < c->arguments->dim; ai++) + { + c->arguments->data[ai] = + ((Expression *) c->arguments->data[ai])->semantic(sc); + } + } + else + { + error("identifier or call expression expected for attribute"); + continue; + } + new_attrs->push(e); + } + + for (unsigned i = 0; i < p_attributes_list.dim; ++i) + { + Expressions ** pa = (Expressions **) p_attributes_list.data[i]; + if (*pa) + { + *pa = (Expressions *) (*pa)->copy(); + (*pa)->append(new_attrs); + } + else + *pa = new_attrs; + } + } + goto Lnodecl; + } #endif else error("unrecognized pragma(%s)", ident->toChars()); @@ -831,6 +958,12 @@ void PragmaDeclaration::semantic(Scope * s->semantic(sc); } } + +#if IN_GCC + if (decl) + if (ident == Id::GNU_attribute) + *sc = sc_save; +#endif return; Lnodecl: diff -uNrp dmd-1.004/src/dmd/class.c gdc-0.22/d/dmd/class.c --- dmd-1.004/src/dmd/class.c 2006-12-31 22:23:20.000000000 +0100 +++ gdc-0.22/d/dmd/class.c 2007-01-27 17:44:01.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + #include #include #include @@ -244,6 +250,10 @@ void ClassDeclaration::semantic(Scope *s scx = scope; // save so we don't make redundant copies scope = NULL; } + if (attributes) + attributes->append(sc->attributes); + else + attributes = sc->attributes; #ifdef IN_GCC methods.setDim(0); #endif @@ -481,6 +491,7 @@ void ClassDeclaration::semantic(Scope *s sc = sc->push(this); sc->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated); + sc->attributes = NULL; sc->parent = this; sc->inunion = 0; @@ -921,6 +932,11 @@ void InterfaceDeclaration::semantic(Scop scope = NULL; } + if (attributes) + attributes->append(sc->attributes); + else + attributes = sc->attributes; + // Expand any tuples in baseclasses[] for (i = 0; i < baseclasses.dim; ) { BaseClass *b = (BaseClass *)baseclasses.data[0]; @@ -1037,6 +1053,7 @@ void InterfaceDeclaration::semantic(Scop } sc = sc->push(this); + sc->attributes = NULL; sc->parent = this; if (isCOMclass()) sc->linkage = LINKwindows; diff -uNrp dmd-1.004/src/dmd/constfold.c gdc-0.22/d/dmd/constfold.c --- dmd-1.004/src/dmd/constfold.c 2006-12-27 11:30:02.000000000 +0100 +++ gdc-0.22/d/dmd/constfold.c 2007-01-27 17:44:01.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + #include #include #include @@ -134,7 +140,22 @@ Expression *CastExp::constFold() { if (e1->type->isfloating()) { integer_t result; +#ifdef IN_GCC + Type * rt = e1->type; + if (rt->iscomplex()) + { + switch (rt->toBasetype()->ty) + { + case Tcomplex32: rt = Type::tfloat32; break; + case Tcomplex64: rt = Type::tfloat64; break; + case Tcomplex80: rt = Type::tfloat80; break; + default: assert(0); + } + } + d_int64 r = e1->toReal().toInt(rt, type); +#else real_t r = e1->toReal(); +#endif switch (type->toBasetype()->ty) { @@ -390,7 +411,7 @@ Expression *MulExp::constFold() #ifdef IN_GCC real_t r; #else - d_float80 r; + d_float80 r; #endif if (e1->type->isreal()) @@ -463,7 +484,7 @@ Expression *DivExp::constFold() #ifdef IN_GCC real_t r; #else - d_float80 r; + d_float80 r; #endif //e1->type->print(); @@ -923,7 +944,7 @@ Expression *EqualExp::constFold() #if __DMC__ cmp = (r1 == r2); #else - if (isnan(r1) || isnan(r2)) // if unordered + if (real_isnan(&r1) || real_isnan(&r2)) // if unordered { cmp = 0; } diff -uNrp dmd-1.004/src/dmd/declaration.c gdc-0.22/d/dmd/declaration.c --- dmd-1.004/src/dmd/declaration.c 2007-01-24 16:29:26.000000000 +0100 +++ gdc-0.22/d/dmd/declaration.c 2007-02-03 17:34:12.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + #include #include @@ -32,6 +38,7 @@ Declaration::Declaration(Identifier *id) storage_class = STCundefined; protection = PROTundefined; linkage = LINKdefault; + attributes = NULL; } void Declaration::semantic(Scope *sc) @@ -208,6 +215,10 @@ void TypedefDeclaration::semantic(Scope basetype = basetype->semantic(loc, sc); sem = 2; type = type->semantic(loc, sc); + if (attributes) + attributes->append(sc->attributes); + else + attributes = sc->attributes; if (sc->parent->isFuncDeclaration() && init) semantic2(sc); } @@ -602,6 +613,10 @@ void VarDeclaration::semantic(Scope *sc) this->parent = sc->parent; //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars()); protection = sc->protection; + if (attributes) + attributes->append(sc->attributes); + else + attributes = sc->attributes; //printf("sc->stc = %x\n", sc->stc); //printf("storage_class = %x\n", storage_class); @@ -641,7 +656,7 @@ void VarDeclaration::semantic(Scope *sc) { Argument *arg = Argument::getNth(tt->arguments, i); OutBuffer buf; - buf.printf("_%s_field_%zu", ident->toChars(), i); + buf.printf("_%s_field_%"PRIuSIZE, ident->toChars(), i); buf.writeByte(0); char *name = (char *)buf.extractData(); Identifier *id = new Identifier(name, TOKidentifier); diff -uNrp dmd-1.004/src/dmd/declaration.h gdc-0.22/d/dmd/declaration.h --- dmd-1.004/src/dmd/declaration.h 2007-01-24 16:27:48.000000000 +0100 +++ gdc-0.22/d/dmd/declaration.h 2007-02-03 17:34:12.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + #ifndef DMD_DECLARATION_H #define DMD_DECLARATION_H @@ -80,6 +86,7 @@ struct Declaration : Dsymbol unsigned storage_class; enum PROT protection; enum LINK linkage; + Expressions * attributes; // GCC decl/type attributes Declaration(Identifier *id); void semantic(Scope *sc); @@ -412,6 +419,7 @@ struct FuncDeclaration : Declaration VarDeclaration *vthis; // 'this' parameter (member and nested) VarDeclaration *v_arguments; // '_arguments' parameter #if IN_GCC + VarDeclaration *v_arguments_var; // '_arguments' variable VarDeclaration *v_argptr; // '_argptr' variable #endif Array *parameters; // Array of Argument's for parameters @@ -478,7 +486,8 @@ struct FuncDeclaration : Declaration char *kind(); void toDocBuffer(OutBuffer *buf); - static FuncDeclaration *genCfunc(Type *treturn, char *name); + static FuncDeclaration *genCfunc(Type *treturn, char *name, + Type *t1 = 0, Type *t2 = 0, Type *t3 = 0); Symbol *toSymbol(); Symbol *toThunkSymbol(int offset); // thunk version diff -uNrp dmd-1.004/src/dmd/dump.c gdc-0.22/d/dmd/dump.c --- dmd-1.004/src/dmd/dump.c 2006-11-30 22:09:48.000000000 +0100 +++ gdc-0.22/d/dmd/dump.c 2006-12-17 06:03:04.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + #include #include #include @@ -52,7 +58,7 @@ void Expression::dump(int i) void IntegerExp::dump(int i) { indent(i); - printf("%p %jd type=%s\n", this, (intmax_t)value, type_print(type)); + printf("%p %"PRIdMAX" type=%s\n", this, (intmax_t)value, type_print(type)); } void IdentifierExp::dump(int i) diff -uNrp dmd-1.004/src/dmd/enum.c gdc-0.22/d/dmd/enum.c --- dmd-1.004/src/dmd/enum.c 2007-01-01 00:39:58.000000000 +0100 +++ gdc-0.22/d/dmd/enum.c 2007-01-27 17:44:01.000000000 +0100 @@ -7,6 +7,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + #include #include @@ -26,6 +32,7 @@ EnumDeclaration::EnumDeclaration(Loc loc maxval = 0; minval = 0; defaultval = 0; + attributes = NULL; } Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s) @@ -57,6 +64,10 @@ void EnumDeclaration::semantic(Scope *sc if (!memtype) memtype = Type::tint32; parent = sc->scopesym; + if (attributes) + attributes->append(sc->attributes); + else + attributes = sc->attributes; memtype = memtype->semantic(loc, sc); /* Check to see if memtype is forward referenced diff -uNrp dmd-1.004/src/dmd/enum.h gdc-0.22/d/dmd/enum.h --- dmd-1.004/src/dmd/enum.h 2006-10-05 16:03:52.000000000 +0200 +++ gdc-0.22/d/dmd/enum.h 2007-01-27 17:44:01.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + #ifndef DMD_ENUM_H #define DMD_ENUM_H @@ -32,6 +38,7 @@ struct EnumDeclaration : ScopeDsymbol integer_t maxval; integer_t minval; integer_t defaultval; // default initializer + Expressions * attributes; // GCC decl/type attributes EnumDeclaration(Loc loc, Identifier *id, Type *memtype); Dsymbol *syntaxCopy(Dsymbol *s); diff -uNrp dmd-1.004/src/dmd/expression.c gdc-0.22/d/dmd/expression.c --- dmd-1.004/src/dmd/expression.c 2007-01-23 13:43:14.000000000 +0100 +++ gdc-0.22/d/dmd/expression.c 2007-02-03 17:34:12.000000000 +0100 @@ -8,6 +8,15 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + +// Issues with using -include total.h (defines integer_t) and then complex.h fails... +#undef integer_t + #include #include #include @@ -15,19 +24,14 @@ #include #include -#if _WIN32 && __DMC__ -extern "C" char * __cdecl __locale_decpoint; -#endif - -#if IN_GCC -// Issues with using -include total.h (defines integer_t) and then complex.h fails... -#undef integer_t -#endif - #ifdef __APPLE__ #define integer_t dmd_integer_t #endif +#if _WIN32 && __DMC__ +extern "C" char * __cdecl __locale_decpoint; +#endif + #if IN_GCC #include "mem.h" #elif _WIN32 @@ -35,7 +39,6 @@ extern "C" char * __cdecl __locale_decpo #elif linux #include "../root/mem.h" #endif - #include "port.h" #include "mtype.h" #include "init.h" @@ -374,7 +377,7 @@ void functionArguments(Loc loc, Scope *s size_t nparams = Argument::dim(tf->parameters); if (nargs > nparams && tf->varargs == 0) - error(loc, "expected %zu arguments, not %zu", nparams, nargs); + error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs); n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams) @@ -398,7 +401,7 @@ void functionArguments(Loc loc, Scope *s { if (tf->varargs == 2 && i + 1 == nparams) goto L2; - error(loc, "expected %zu arguments, not %zu", nparams, nargs); + error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs); break; } arg = p->defaultArg->copy(); @@ -412,7 +415,7 @@ void functionArguments(Loc loc, Scope *s if (arg->implicitConvTo(p->type)) { if (nargs != nparams) - error(loc, "expected %zu arguments, not %zu", nparams, nargs); + error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs); goto L1; } L2: @@ -1002,7 +1005,7 @@ char *IntegerExp::toChars() { static char buffer[sizeof(value) * 3 + 1]; - sprintf(buffer, "%jd", value); + sprintf(buffer, "%"PRIdMAX, value); return buffer; } @@ -1176,11 +1179,11 @@ void IntegerExp::toCBuffer(OutBuffer *bu break; case Tint64: - buf->printf("%jdL", v); + buf->printf("%"PRIdMAX"L", v); break; case Tuns64: - buf->printf("%juLU", v); + buf->printf("%"PRIuMAX"LU", v); break; case Tbit: @@ -1202,17 +1205,17 @@ void IntegerExp::toCBuffer(OutBuffer *bu } } else if (v & 0x8000000000000000LL) - buf->printf("0x%jx", v); + buf->printf("0x%"PRIxMAX, v); else - buf->printf("%jd", v); + buf->printf("%"PRIdMAX, v); } void IntegerExp::toMangleBuffer(OutBuffer *buf) { if ((sinteger_t)value < 0) - buf->printf("N%jd", -value); + buf->printf("N%"PRIdMAX, -value); else - buf->printf("%jd", value); + buf->printf("%"PRIdMAX, value); } /******************************** RealExp **************************/ @@ -1285,11 +1288,15 @@ complex_t RealExp::toComplex() int RealEquals(real_t x1, real_t x2) { +#ifndef IN_GCC return (isnan(x1) && isnan(x2)) || /* In some cases, the REALPAD bytes get garbage in them, * so be sure and ignore them. */ memcmp(&x1, &x2, REALSIZE - REALPAD) == 0; +#else + return (x1.isNan() && x2.isNan()) || x1.isIdenticalTo(x2); +#endif } int RealExp::equals(Object *o) @@ -1324,14 +1331,27 @@ int RealExp::isBool(int result) #endif } -void floatToBuffer(OutBuffer *buf, Type *type, real_t value) +void floatToBuffer(OutBuffer *buf, Type *type, const real_t & value) { /* In order to get an exact representation, try converting it * to decimal then back again. If it matches, use it. * If it doesn't, fall back to hex, which is * always exact. */ - char buffer[25]; + char buffer[48]; +#ifdef IN_GCC + real_t parsed_value; + + value.format(buffer, sizeof(buffer)); + parsed_value = real_t::parse(buffer, real_t::LongDouble); + if (parsed_value.isIdenticalTo( value )) + buf->writestring(buffer); + else + { + value.formatHex(buffer, sizeof(buffer)); + buf->writestring(buffer); + } +#else sprintf(buffer, "%Lg", value); assert(strlen(buffer) < sizeof(buffer)); #if _WIN32 && __DMC__ @@ -1346,6 +1366,7 @@ void floatToBuffer(OutBuffer *buf, Type buf->writestring(buffer); else buf->printf("%La", value); // ensure exact duplication +#endif if (type) { @@ -1390,13 +1411,25 @@ void realToMangleBuffer(OutBuffer *buf, * 0X1.9P+2 => 19P2 */ +#ifdef IN_GCC + if (value.isNan()) + buf->writestring("NAN"); // no -NAN bugs + else if (value.isInf()) + buf->writestring(value.isNegative()?"NINF":"INF"); +#else if (isnan(value)) buf->writestring("NAN"); // no -NAN bugs +#endif else { - char buffer[32]; + char buffer[64]; +#ifdef IN_GCC + value.formatHex(buffer, sizeof(buffer)); + int n = strlen(buffer); +#else int n = sprintf(buffer, "%LA", value); assert(n > 0 && n < sizeof(buffer)); +#endif for (int i = 0; i < n; i++) { char c = buffer[i]; @@ -1407,6 +1440,7 @@ void realToMangleBuffer(OutBuffer *buf, break; case '+': + case 'x': case 'X': case '.': break; @@ -1495,10 +1529,15 @@ int ComplexExp::equals(Object *o) if (this == o || (((Expression *)o)->op == TOKcomplex80 && ((ne = (ComplexExp *)o), type->equals(ne->type)) && - RealEquals(creall(value), creall(ne->value)) && - RealEquals(cimagl(value), cimagl(ne->value)) +#ifndef IN_GCC + RealEquals(creall(value), creall(ne->value)) && + RealEquals(cimagl(value), cimagl(ne->value)) +#else + RealEquals(value.re, ne->value.re) && + RealEquals(value.im, ne->value.im) +#endif + ) ) - ) return 1; return 0; } @@ -2361,8 +2400,8 @@ void StringExp::toMangleBuffer(OutBuffer { char m; OutBuffer tmp; char *p; - unsigned c; - unsigned u; + dchar_t c; + size_t u; unsigned char *q; unsigned qlen; @@ -5808,7 +5847,7 @@ Expression *SliceExp::semantic(Scope *sc } else { - error("string slice [%ju .. %ju] is out of bounds", i1, i2); + error("string slice [%"PRIuMAX" .. %"PRIuMAX"] is out of bounds", i1, i2); e = e1; } return e; @@ -6163,7 +6202,7 @@ Expression *IndexExp::semantic(Scope *sc } else { - error("array index [%ju] is outside array bounds [0 .. %zu]", + error("array index [%"PRIuMAX"] is outside array bounds [0 .. %"PRIuSIZE"]", index, length); e = e1; } diff -uNrp dmd-1.004/src/dmd/expression.h gdc-0.22/d/dmd/expression.h --- dmd-1.004/src/dmd/expression.h 2006-12-30 18:15:14.000000000 +0100 +++ gdc-0.22/d/dmd/expression.h 2007-01-27 17:44:01.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + #ifndef DMD_EXPRESSION_H #define DMD_EXPRESSION_H diff -uNrp dmd-1.004/src/dmd/func.c gdc-0.22/d/dmd/func.c --- dmd-1.004/src/dmd/func.c 2007-01-01 20:30:28.000000000 +0100 +++ gdc-0.22/d/dmd/func.c 2007-01-27 17:44:01.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + #include #include @@ -51,6 +57,7 @@ FuncDeclaration::FuncDeclaration(Loc loc v_arguments = NULL; #if IN_GCC v_argptr = NULL; + v_arguments_var = NULL; #endif parameters = NULL; labtab = NULL; @@ -126,6 +133,10 @@ void FuncDeclaration::semantic(Scope *sc } protection = sc->protection; storage_class |= sc->stc; + if (attributes) + attributes->append(sc->attributes); + else + attributes = sc->attributes; //printf("function storage_class = x%x\n", storage_class); Dsymbol *parent = toParent(); @@ -587,6 +598,7 @@ void FuncDeclaration::semantic3(Scope *s sc2->fes = fes; sc2->linkage = LINKd; sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated); + sc2->attributes = NULL; sc2->protection = PROTpublic; sc2->explicitProtection = 0; sc2->structalign = 8; @@ -701,7 +713,7 @@ void FuncDeclaration::semantic3(Scope *s { //error("no identifier for parameter %d of %s", i + 1, toChars()); OutBuffer buf; - buf.printf("_param_%zu", i); + buf.printf("_param_%"PRIuSIZE, i); char *name = (char *)buf.extractData(); id = new Identifier(name, TOKidentifier); arg->ident = id; @@ -1056,6 +1068,10 @@ void FuncDeclaration::semantic3(Scope *s if (_arguments) { +#if IN_GCC + v_arguments_var = _arguments; + v_arguments_var->init = new VoidInitializer(loc); +#endif /* Advance to elements[] member of TypeInfo_Tuple with: * _arguments = v_arguments.elements; */ @@ -1696,7 +1712,8 @@ int FuncDeclaration::addPostInvariant() * Generate a FuncDeclaration for a runtime library function. */ -FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, char *name) +FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, char *name, + Type *t1, Type *t2, Type *t3) { FuncDeclaration *fd; TypeFunction *tf; @@ -1721,7 +1738,19 @@ FuncDeclaration *FuncDeclaration::genCfu } else { - tf = new TypeFunction(NULL, treturn, 0, LINKc); + Arguments * args = 0; + if (t1) { + args = new Arguments; + args->push(new Argument(In,t1,0,0)); + if (t2) + { + args->push(new Argument(In,t2,0,0)); + if (t3) + args->push(new Argument(In,t3,0,0)); + } + } + + tf = new TypeFunction(args, treturn, 0, LINKc); fd = new FuncDeclaration(0, 0, id, STCstatic, tf); fd->protection = PROTpublic; fd->linkage = LINKc; diff -uNrp dmd-1.004/src/dmd/html.c gdc-0.22/d/dmd/html.c --- dmd-1.004/src/dmd/html.c 2006-11-19 19:56:40.000000000 +0100 +++ gdc-0.22/d/dmd/html.c 2006-12-17 06:03:04.000000000 +0100 @@ -7,6 +7,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 + Modified by Thomas Kuehne, November 2004 +*/ /* HTML parser */ @@ -16,19 +22,17 @@ #include #include #include -#include +//#include #include "mars.h" #include "html.h" #include #include "root.h" -#include "../mars/mars.h" +//#include "../mars/mars.h" extern int HtmlNamedEntity(unsigned char *p, int length); -static int isLineSeparator(const unsigned char* p); - /********************************** * Determine if beginning of tag identifier * or a continuation of a tag identifier. @@ -36,7 +40,7 @@ static int isLineSeparator(const unsigne inline int istagstart(int c) { - return (isalpha(c) || c == '_'); + return (isalpha(c) || c == '_' || c == '!'); } inline int istag(int c) @@ -44,12 +48,41 @@ inline int istag(int c) return (isalnum(c) || c == '_'); } +/** + * identify DOS, Linux, Mac, Next and Unicode line endings + * 0 if this is no line seperator + * >0 the length of the seperator + * Note: input has to be UTF-8 + */ +static int isLineSeperator(const unsigned char* p){ + // Linux + if( p[0]=='\n'){ + return 1; + } + + // Mac & Dos + if( p[0]=='\r'){ + return (p[1]=='\n') ? 2 : 1; + } + + // Unicode (line || paragarph sep.) + if( p[0]==0xE2 && p[1]==0x80 && (p[2]==0xA8 || p[2]==0xA9)){ + return 3; + } + + // Next + if( p[0]==0xC2 && p[1]==0x85){ + return 2; + } + + return 0; +} + /********************************************** */ Html::Html(const char *sourcename, unsigned char *base, unsigned length) { - //printf("Html::Html()\n"); this->sourcename = sourcename; this->base = base; p = base; @@ -67,18 +100,19 @@ void Html::error(const char *format, ... { if (!global.gag) { - printf("%s(%d) : HTML Error: ", sourcename, linnum); + fprintf(stderr, "%s:%d: HTML Error: ", sourcename, linnum); va_list ap; va_start(ap, format); - vprintf(format, ap); + vfprintf(stderr, format, ap); va_end(ap); - printf("\n"); - fflush(stdout); + fprintf(stderr, "\n"); + fflush(stderr); } global.errors++; + fatal(); } /********************************************** @@ -102,12 +136,23 @@ void Html::extractCode(OutBuffer *buf) case '\'': skipString(); continue; + */ #endif case '<': + //-OLDOLDREMOVE// if (p[1] == '!' && p[2] == '-' && p[3] == '-') if (p[1] == '!' && isCommentStart()) { // Comments start with of comment"); break; default: - Ldefault: + // Ldefault: + int lineSepLength = isLineSeperator(p); + if( lineSepLength>0 ){ + linnum++; // remember to count lines + // Always extract new lines, so that D lexer counts + // the lines right. + dbuf->writeByte('\n'); // BUG: wchar + p+=lineSepLength-1; + continue; + } scangt = 0; // it's not --> continue; } @@ -446,7 +542,7 @@ void Html::scanComment() //printf("*p = '%c'\n", *p); } -/******************************************** + /******************************************** * Determine if we are at the start of a comment. * Input: * p is on the opening '<' @@ -524,7 +620,7 @@ void Html::scanCDATA() { while(*p && *p != 0x1A) { - int lineSepLength = isLineSeparator(p); + int lineSepLength = isLineSeperator(p); if (lineSepLength>0) { /* Always extract new lines, so that D lexer counts the lines @@ -577,6 +673,7 @@ int Html::charEntity() } else hex = 0; + if (p[1] == ';') goto Linvalid; while (1) @@ -680,40 +777,11 @@ int Html::charEntity() // Kludge to convert non-breaking space to ascii space if (c == 160) - c = ' '; - + c = 32; return c; - Lignore: //printf("Lignore\n"); p = pstart + 1; return '&'; } -/** - * identify DOS, Linux, Mac, Next and Unicode line endings - * 0 if this is no line separator - * >0 the length of the separator - * Note: input has to be UTF-8 - */ -static int isLineSeparator(const unsigned char* p) -{ - // Linux - if( p[0]=='\n') - return 1; - - // Mac & Dos - if( p[0]=='\r') - return (p[1]=='\n') ? 2 : 1; - - // Unicode (line || paragraph sep.) - if( p[0]==0xE2 && p[1]==0x80 && (p[2]==0xA8 || p[2]==0xA9)) - return 3; - - // Next - if( p[0]==0xC2 && p[1]==0x85) - return 2; - - return 0; -} - diff -uNrp dmd-1.004/src/dmd/identifier.c gdc-0.22/d/dmd/identifier.c --- dmd-1.004/src/dmd/identifier.c 2006-11-21 02:12:48.000000000 +0100 +++ gdc-0.22/d/dmd/identifier.c 2006-12-17 06:03:04.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, May 2005 +*/ + #include #include diff -uNrp dmd-1.004/src/dmd/idgen.c gdc-0.22/d/dmd/idgen.c --- dmd-1.004/src/dmd/idgen.c 2006-12-07 02:10:38.000000000 +0100 +++ gdc-0.22/d/dmd/idgen.c 2007-01-31 01:52:39.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, January 2007 +*/ + // Program to generate string files in d data structures. // Saves much tedious typing, and eliminates typo problems. // Generates: @@ -26,7 +32,7 @@ struct Msgtable char *name; // name in D executable }; -Msgtable msgtable[] = +struct Msgtable msgtable[] = { { "IUnknown" }, { "Object" }, @@ -196,6 +202,8 @@ Msgtable msgtable[] = { "lib" }, { "msg" }, { "GNU_asm" }, + { "GNU_attribute" }, + { "GNU_set_attribute" }, // For toHash/toString { "tohash", "toHash" }, diff -uNrp dmd-1.004/src/dmd/impcnvgen.c gdc-0.22/d/dmd/impcnvgen.c --- dmd-1.004/src/dmd/impcnvgen.c 2006-02-22 09:52:16.000000000 +0100 +++ gdc-0.22/d/dmd/impcnvgen.c 2007-01-31 01:52:39.000000000 +0100 @@ -7,9 +7,16 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, January 2007 +*/ + #include #include +#define ENUM_TY_ONLY #include "mtype.h" enum TY impcnvResult[TMAX][TMAX]; diff -uNrp dmd-1.004/src/dmd/init.c gdc-0.22/d/dmd/init.c --- dmd-1.004/src/dmd/init.c 2006-12-30 11:42:56.000000000 +0100 +++ gdc-0.22/d/dmd/init.c 2007-01-27 17:44:01.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + #include #include @@ -346,9 +352,9 @@ Initializer *ArrayInitializer::semantic( if (length > dim) dim = length; } - unsigned long amax = 0x80000000; - if ((unsigned long) dim * t->next->size() >= amax) - error(loc, "array dimension %u exceeds max of %ju", dim, amax / t->next->size()); + uintmax_t amax = 0x80000000; + if ((uintmax_t) dim * t->next->size() >= amax) + error(loc, "array dimension %u exceeds max of %"PRIuMAX, dim, amax / t->next->size()); return this; } diff -uNrp dmd-1.004/src/dmd/lexer.c gdc-0.22/d/dmd/lexer.c --- dmd-1.004/src/dmd/lexer.c 2006-12-15 00:03:54.000000000 +0100 +++ gdc-0.22/d/dmd/lexer.c 2007-01-27 17:44:01.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + /* Lexical Analyzer */ #include @@ -15,7 +21,7 @@ #include #include #include -#include +//#include #include #include #include @@ -130,16 +136,16 @@ char *Token::toChars() #if IN_GCC sprintf(buffer,"%uU",(d_uns32)uns64value); #else - sprintf(buffer,"%uU",uns32value); + sprintf(buffer,"%uU",uns32value); #endif break; case TOKint64v: - sprintf(buffer,"%jdL",int64value); + sprintf(buffer,"%"PRIdMAX"L",int64value); break; case TOKuns64v: - sprintf(buffer,"%juUL",uns64value); + sprintf(buffer,"%"PRIuMAX"UL",uns64value); break; #if IN_GCC @@ -181,6 +187,7 @@ char *Token::toChars() break; #endif + case TOKstring: #if CSTRINGS p = string; @@ -328,7 +335,7 @@ void Lexer::error(const char *format, .. fprintf(stdmsg, "\n"); fflush(stdmsg); - + if (global.errors >= 20) // moderate blizzard of cascading messages fatal(); } diff -uNrp dmd-1.004/src/dmd/mangle.c gdc-0.22/d/dmd/mangle.c --- dmd-1.004/src/dmd/mangle.c 2006-12-14 19:16:56.000000000 +0100 +++ gdc-0.22/d/dmd/mangle.c 2007-01-27 17:44:01.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + #include #include #include @@ -206,7 +212,7 @@ char *Dsymbol::mangle() p += 2; buf.writestring(p); } - buf.printf("%zu%s", strlen(id), id); + buf.printf("%"PRIuSIZE"%s", strlen(id), id); id = buf.toChars(); buf.data = NULL; return id; diff -uNrp dmd-1.004/src/dmd/mars.h gdc-0.22/d/dmd/mars.h --- dmd-1.004/src/dmd/mars.h 2007-01-09 13:34:04.000000000 +0100 +++ gdc-0.22/d/dmd/mars.h 2007-02-03 17:34:12.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + #ifndef DMD_MARS_H #define DMD_MARS_H @@ -17,6 +23,9 @@ #include #include +#define __STDC_FORMAT_MACROS 1 +#include +#include #ifdef IN_GCC /* Changes for the GDC compiler by David Friedman */ @@ -79,7 +88,7 @@ struct Param Array *versionids; // version identifiers bool dump_source; - + // Hidden debug switches char debuga; char debugb; @@ -172,7 +181,6 @@ typedef d_uns32 d_dchar; #else typedef long double real_t; #endif - // Modify OutBuffer::writewchar to write the correct size of wchar #if _WIN32 #define writewchar writeword @@ -185,6 +193,17 @@ typedef long double real_t; #include "d-gcc-complex_t.h" #endif +#if __MSVCRT__ +#define PRIuSIZE "Iu" +#define PRIxSIZE "Ix" +#elif __NEWLIB_H__ +#define PRIuSIZE "u" +#define PRIxSIZE "x" +#else +#define PRIuSIZE "zu" +#define PRIxSIZE "zx" +#endif + struct Module; //typedef unsigned Loc; // file location diff -uNrp dmd-1.004/src/dmd/mem.c gdc-0.22/d/dmd/mem.c --- dmd-1.004/src/dmd/mem.c 2005-04-27 00:21:12.000000000 +0200 +++ gdc-0.22/d/dmd/mem.c 2006-06-02 05:31:29.000000000 +0200 @@ -2,11 +2,19 @@ /* Copyright (c) 2000 Digital Mars */ /* All Rights Reserved */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, May 2005 +*/ + #include #include #include -#if linux +#if IN_GCC +#include "mem.h" +#elif linux #include "../root/mem.h" #else #include "mem.h" @@ -110,7 +118,7 @@ void *Mem::mallocdup(void *o, size_t siz void Mem::error() { - printf("Error: out of memory\n"); + fprintf(stderr, "Error: out of memory\n"); exit(EXIT_FAILURE); } @@ -130,7 +138,7 @@ void * operator new(size_t m_size) void *p = malloc(m_size); if (p) return p; - printf("Error: out of memory\n"); + fprintf(stderr, "Error: out of memory\n"); exit(EXIT_FAILURE); return p; } diff -uNrp dmd-1.004/src/dmd/mem.h gdc-0.22/d/dmd/mem.h --- dmd-1.004/src/dmd/mem.h 2006-10-25 14:33:40.000000000 +0200 +++ gdc-0.22/d/dmd/mem.h 2006-06-02 05:31:29.000000000 +0200 @@ -1,10 +1,16 @@ // Copyright (C) 2000-2001 by Chromium Communications // All Rights Reserved +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + #ifndef ROOT_MEM_H #define ROOT_MEM_H -#include // for size_t +#include // for size_t typedef void (*FINALIZERPROC)(void* pObj, void* pClientData); diff -uNrp dmd-1.004/src/dmd/module.c gdc-0.22/d/dmd/module.c --- dmd-1.004/src/dmd/module.c 2007-01-25 21:53:48.000000000 +0100 +++ gdc-0.22/d/dmd/module.c 2007-02-03 17:34:12.000000000 +0100 @@ -235,7 +235,7 @@ Module *Module::load(Loc loc, Array *pac if (global.params.verbose) { - printf("import "); + fprintf(stdmsg, "import "); if (packages) { for (size_t i = 0; i < packages->dim; i++) @@ -243,7 +243,7 @@ Module *Module::load(Loc loc, Array *pac printf("%s.", pid->toChars()); } } - printf("%s\n", ident->toChars()); + fprintf(stdmsg, "%s\n", ident->toChars()); } // Build module filename by turning: diff -uNrp dmd-1.004/src/dmd/mtype.c gdc-0.22/d/dmd/mtype.c --- dmd-1.004/src/dmd/mtype.c 2007-01-24 16:35:04.000000000 +0100 +++ gdc-0.22/d/dmd/mtype.c 2007-02-03 18:35:36.000000000 +0100 @@ -8,6 +8,15 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + +// Issues with using -include total.h (defines integer_t) and then complex.h fails... +#undef integer_t + #define __USE_ISOC99 1 // so signbit() gets defined #include @@ -15,15 +24,21 @@ #include #include +#include "gdc_alloca.h" + #ifdef __DMC__ #include #endif +// TODO%% this undefines signbit and includes is the wrong complex.h anyway +// -- not sure why this is needed, anyway +// don't need to worry about all this if the 'nan negative by default' issue is resolved #if _MSC_VER #include #include #include #elif __DMC__ +// includes the wrong complex.h in C++ #include #else //#define signbit 56 @@ -34,11 +49,26 @@ static double zero = 0; #elif __GNUC__ #include -#include -#include +// %% shouldn't be necessary +//#include +//#include static double zero = 0; #endif +#ifndef NAN +#define NAN (nan("0")) +#endif +#ifndef INFINITY +#define INFINITY (infinity()) +#endif + + + +#ifdef __APPLE__ +#define integer_t dmd_integer_t +#endif + + #include "mem.h" #include "dsymbol.h" @@ -981,6 +1011,38 @@ Expression *TypeBasic::getProperty(Loc l case Tcomplex32: case Timaginary32: +#ifdef IN_GCC + // %% lazy, fix +#define FLT_MAX real_t_properties[real_t::Float].maxval; +#define DBL_MAX real_t_properties[real_t::Double].maxval; +#define LDBL_MAX real_t_properties[real_t::LongDouble].maxval; +#define FLT_MIN real_t_properties[real_t::Float].minval; +#define DBL_MIN real_t_properties[real_t::Double].minval; +#define LDBL_MIN real_t_properties[real_t::LongDouble].minval; +#define FLT_DIG real_t_properties[real_t::Float].dig; +#define DBL_DIG real_t_properties[real_t::Double].dig; +#define LDBL_DIG real_t_properties[real_t::LongDouble].dig; +#define FLT_MANT_DIG real_t_properties[real_t::Float].mant_dig; +#define DBL_MANT_DIG real_t_properties[real_t::Double].mant_dig; +#define LDBL_MANT_DIG real_t_properties[real_t::LongDouble].mant_dig; +#define FLT_MAX_10_EXP real_t_properties[real_t::Float].max_10_exp; +#define DBL_MAX_10_EXP real_t_properties[real_t::Double].max_10_exp; +#define LDBL_MAX_10_EXP real_t_properties[real_t::LongDouble].max_10_exp; +#define FLT_MIN_10_EXP real_t_properties[real_t::Float].min_10_exp; +#define DBL_MIN_10_EXP real_t_properties[real_t::Double].min_10_exp; +#define LDBL_MIN_10_EXP real_t_properties[real_t::LongDouble].min_10_exp; +#define FLT_MAX_EXP real_t_properties[real_t::Float].max_exp; +#define DBL_MAX_EXP real_t_properties[real_t::Double].max_exp; +#define LDBL_MAX_EXP real_t_properties[real_t::LongDouble].max_exp; +#define FLT_MIN_EXP real_t_properties[real_t::Float].min_exp; +#define DBL_MIN_EXP real_t_properties[real_t::Double].min_exp; +#define LDBL_MIN_EXP real_t_properties[real_t::LongDouble].min_exp; +#define FLT_EPSILON real_t_properties[real_t::Float].epsilonval; +#define DBL_EPSILON real_t_properties[real_t::Double].epsilonval; +#define LDBL_EPSILON real_t_properties[real_t::LongDouble].epsilonval; + + +#endif case Tfloat32: fvalue = FLT_MAX; goto Lfvalue; case Tcomplex64: case Timaginary64: @@ -1247,7 +1309,7 @@ Expression *TypeBasic::dotExp(Scope *sc, case Timaginary64: t = tfloat64; goto L2; case Timaginary80: t = tfloat80; goto L2; L2: - e = new RealExp(0, 0.0, t); + e = new RealExp(0, 0, t); break; default: @@ -1277,7 +1339,7 @@ Expression *TypeBasic::dotExp(Scope *sc, case Tfloat32: case Tfloat64: case Tfloat80: - e = new RealExp(0, 0.0, this); + e = new RealExp(0, 0, this); break; default: @@ -1457,7 +1519,7 @@ Expression *TypeArray::dotExp(Scope *sc, static char *name[2] = { "_adReverseChar", "_adReverseWchar" }; nm = name[n->ty == Twchar]; - fd = FuncDeclaration::genCfunc(Type::tindex, nm); + fd = FuncDeclaration::genCfunc(Type::tindex, nm, Type::tvoid->arrayOf()); ec = new VarExp(0, fd); e = e->castTo(sc, n->arrayOf()); // convert to dynamic array arguments = new Expressions(); @@ -1474,7 +1536,7 @@ Expression *TypeArray::dotExp(Scope *sc, static char *name[2] = { "_adSortChar", "_adSortWchar" }; nm = name[n->ty == Twchar]; - fd = FuncDeclaration::genCfunc(Type::tindex, nm); + fd = FuncDeclaration::genCfunc(Type::tindex, nm, Type::tvoid->arrayOf()); ec = new VarExp(0, fd); e = e->castTo(sc, n->arrayOf()); // convert to dynamic array arguments = new Expressions(); @@ -1495,7 +1557,12 @@ Expression *TypeArray::dotExp(Scope *sc, assert(size); dup = (ident == Id::dup); nm = name[dup]; - fd = FuncDeclaration::genCfunc(Type::tindex, nm); + if (dup) + fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), nm, + Type::typeinfo->type, Type::tvoid->arrayOf()); + else + fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), nm, + Type::tvoid->arrayOf(), Type::tint32); ec = new VarExp(0, fd); e = e->castTo(sc, n->arrayOf()); // convert to dynamic array arguments = new Expressions(); @@ -1514,7 +1581,9 @@ Expression *TypeArray::dotExp(Scope *sc, Expressions *arguments; fd = FuncDeclaration::genCfunc(tint32->arrayOf(), - (char*)(n->ty == Tbit ? "_adSortBit" : "_adSort")); + (char*)(n->ty == Tbit ? "_adSortBit" : "_adSort"), + Type::tvoid->arrayOf(), + n->ty == Tbit ? NULL : Type::tvoid->pointerTo()); ec = new VarExp(0, fd); e = e->castTo(sc, n->arrayOf()); // convert to dynamic array arguments = new Expressions(); @@ -1627,7 +1696,7 @@ d_uns64 TypeSArray::size(Loc loc) return sz; Loverflow: - error(loc, "index %jd overflow for static array", sz); + error(loc, "index %"PRIdMAX" overflow for static array", sz); return 1; } @@ -1712,7 +1781,7 @@ Type *TypeSArray::semantic(Loc loc, Scop if (n && n2 / n != d2) { Loverflow: - error(loc, "index %jd overflow for static array", d1); + error(loc, "index %"PRIdMAX" overflow for static array", d1); dim = new IntegerExp(0, 1, tsize_t); } } @@ -1726,7 +1795,7 @@ Type *TypeSArray::semantic(Loc loc, Scop uinteger_t d = dim->toUInteger(); if (d >= tt->arguments->dim) - { error(loc, "tuple index %ju exceeds %u", d, tt->arguments->dim); + { error(loc, "tuple index %"PRIuMAX" exceeds %u", d, tt->arguments->dim); return Type::terror; } Argument *arg = (Argument *)tt->arguments->data[(size_t)d]; @@ -1747,7 +1816,7 @@ void TypeSArray::toDecoBuffer(OutBuffer { buf->writeByte(mangleChar[ty]); if (dim) - buf->printf("%ju", dim->toInteger()); + buf->printf("%"PRIuMAX, dim->toInteger()); if (next) next->toDecoBuffer(buf); } @@ -2120,7 +2189,7 @@ Expression *TypeAArray::dotExp(Scope *sc FuncDeclaration *fd; Expressions *arguments; - fd = FuncDeclaration::genCfunc(Type::tsize_t, "_aaLen"); + fd = FuncDeclaration::genCfunc(Type::tsize_t, "_aaLen", Type::tvoid->arrayOf()); ec = new VarExp(0, fd); arguments = new Expressions(); arguments->push(e); @@ -2145,7 +2214,8 @@ Expression *TypeAArray::dotExp(Scope *sc else #endif strcpy(aakeys, "_aaKeys"); - fd = FuncDeclaration::genCfunc(Type::tindex, aakeys); + fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), aakeys, + Type::tvoid->arrayOf(), Type::tsize_t); ec = new VarExp(0, fd); arguments = new Expressions(); arguments->push(e); @@ -2160,7 +2230,8 @@ Expression *TypeAArray::dotExp(Scope *sc FuncDeclaration *fd; Expressions *arguments; - fd = FuncDeclaration::genCfunc(Type::tindex, "_aaValues"); + fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), "_aaValues", + Type::tvoid->arrayOf(), Type::tsize_t, Type::tsize_t); ec = new VarExp(0, fd); arguments = new Expressions(); arguments->push(e); @@ -2177,7 +2248,7 @@ Expression *TypeAArray::dotExp(Scope *sc FuncDeclaration *fd; Expressions *arguments; - fd = FuncDeclaration::genCfunc(Type::tint64, "_aaRehash"); + fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), "_aaRehash"); ec = new VarExp(0, fd); arguments = new Expressions(); arguments->push(e->addressOf(sc)); @@ -2884,7 +2955,19 @@ Expression *TypeDelegate::dotExp(Scope * #endif if (ident == Id::ptr) { +#ifndef IN_GCC e->type = tvoidptr; +#else + if (e->op == TOKdelegate || e->op == TOKcast) + e = e->castTo(sc, tvoidptr); // Not an lvalue + else + { + e = e->addressOf(sc); + e = e->castTo(sc, tvoidptr->pointerTo()); + e = new PtrExp(e->loc, e); + e->type = tvoidptr; + } +#endif return e; } else if (ident == Id::funcptr) @@ -4697,7 +4780,13 @@ void TypeTuple::toDecoBuffer(OutBuffer * OutBuffer buf2; Argument::argsToDecoBuffer(&buf2, arguments); unsigned len = buf2.offset; +#if __NEWLIB_H__ + // newlib bug as of 1.14.0 + char * p = (char*) buf2.extractData(); + buf->printf("%c%d%.*s", mangleChar[ty], len, len, p ? p : ""); +#else buf->printf("%c%d%.*s", mangleChar[ty], len, len, (char *)buf2.extractData()); +#endif } Expression *TypeTuple::getProperty(Loc loc, Identifier *ident) @@ -4758,7 +4847,7 @@ Type *TypeSlice::semantic(Loc loc, Scope uinteger_t i2 = upr->toUInteger(); if (!(i1 <= i2 && i2 <= tt->arguments->dim)) - { error(loc, "slice [%ju..%ju] is out of range of [0..%u]", i1, i2, tt->arguments->dim); + { error(loc, "slice [%"PRIuMAX"..%"PRIuMAX"] is out of range of [0..%u]", i1, i2, tt->arguments->dim); return Type::terror; } diff -uNrp dmd-1.004/src/dmd/mtype.h gdc-0.22/d/dmd/mtype.h --- dmd-1.004/src/dmd/mtype.h 2007-01-13 14:15:48.000000000 +0100 +++ gdc-0.22/d/dmd/mtype.h 2007-02-03 17:34:12.000000000 +0100 @@ -8,9 +8,17 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, January 2007 +*/ + #ifndef DMD_MTYPE_H #define DMD_MTYPE_H +#ifndef ENUM_TY_ONLY + #ifdef __DMC__ #pragma once #endif /* __DMC__ */ @@ -46,6 +54,8 @@ typedef struct TYPE type; #endif struct Symbol; +#endif + enum TY { Tarray, // dynamic array @@ -97,6 +107,8 @@ enum TY TMAX }; +#ifndef ENUM_TY_ONLY + #define Tascii Tchar extern int Tsize_t; @@ -687,4 +699,6 @@ extern int REALPAD; extern int Tsize_t; extern int Tptrdiff_t; +#endif + #endif /* DMD_MTYPE_H */ diff -uNrp dmd-1.004/src/dmd/opover.c gdc-0.22/d/dmd/opover.c --- dmd-1.004/src/dmd/opover.c 2006-12-07 01:59:50.000000000 +0100 +++ gdc-0.22/d/dmd/opover.c 2006-12-17 06:03:04.000000000 +0100 @@ -8,6 +8,16 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + + +// Issues with using -include total.h (defines integer_t) and then complex.h fails... +#undef integer_t + #include #include #include diff -uNrp dmd-1.004/src/dmd/optimize.c gdc-0.22/d/dmd/optimize.c --- dmd-1.004/src/dmd/optimize.c 2006-12-30 17:25:00.000000000 +0100 +++ gdc-0.22/d/dmd/optimize.c 2007-01-27 17:44:01.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + #include #include #include @@ -132,7 +138,7 @@ Expression *AddrExp::optimize(int result TypeSArray *ts = (TypeSArray *)ve->type; integer_t dim = ts->dim->toInteger(); if (index < 0 || index >= dim) - error("array index %jd is out of bounds [0..%jd]", index, dim); + error("array index %"PRIdMAX" is out of bounds [0..%"PRIdMAX"]", index, dim); e = new SymOffExp(loc, ve->var, index * ts->next->size()); e->type = type; return e; @@ -155,8 +161,13 @@ Expression *PtrExp::optimize(int result) e = ex; else { +#ifndef IN_GCC e = ex->copy(); e->type = type; +#else + // Stuffing types does not always work in GCC + return this; +#endif } return e; } @@ -232,7 +243,7 @@ Expression *ShlExp::optimize(int result) e2 = e2->constFold(); integer_t i2 = e2->toInteger(); if (i2 < 0 || i2 > e1->type->size() * 8) - { error("shift left by %jd exceeds %zu", i2, e2->type->size() * 8); + { error("shift left by %"PRIdMAX" exceeds %"PRIuSIZE, i2, e2->type->size() * 8); e2 = new IntegerExp(0); } if (e1->isConst() == 1) @@ -386,7 +397,7 @@ Expression *IndexExp::optimize(int resul uinteger_t i = e2->toInteger(); if (i >= es1->len) - error("string index %ju is out of bounds [0 .. %ju]", i, es1->len); + error("string index %"PRIuMAX" is out of bounds [0 .. %"PRIuMAX"]", i, es1->len); else { integer_t value; @@ -417,7 +428,7 @@ Expression *IndexExp::optimize(int resul uinteger_t i = e2->toInteger(); if (i >= length) - { error("array index %ju is out of bounds [0 .. %ju]", i, length); + { error("array index %"PRIuMAX" is out of bounds [0 .. %"PRIuMAX"]", i, length); } else if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2)) { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; @@ -451,7 +462,7 @@ Expression *SliceExp::optimize(int resul uinteger_t iupr = upr->toInteger(); if (iupr > es1->len || ilwr > iupr) - error("string slice [%ju .. %ju] is out of bounds", ilwr, iupr); + error("string slice [%"PRIuMAX" .. %"PRIuMAX"] is out of bounds", ilwr, iupr); else { integer_t value; void *s; @@ -478,7 +489,7 @@ Expression *SliceExp::optimize(int resul uinteger_t iupr = upr->toInteger(); if (iupr > es1->elements->dim || ilwr > iupr) - error("array slice [%ju .. %ju] is out of bounds", ilwr, iupr); + error("array slice [%"PRIuMAX" .. %"PRIuMAX"] is out of bounds", ilwr, iupr); else { memmove(es1->elements->data, @@ -587,6 +598,7 @@ Expression *CatExp::optimize(int result) { // Concatenate the strings void *s; + void *sch; StringExp *es1 = (StringExp *)e1; StringExp *es; Type *t; @@ -596,7 +608,14 @@ Expression *CatExp::optimize(int result) s = mem.malloc((len + 1) * sz); memcpy(s, es1->string, es1->len * sz); - memcpy((unsigned char *)s + es1->len * sz, &v, sz); + sch = (unsigned char *)s + es1->len * sz; + switch (sz) + { + case 1: *(d_uns8*)sch = v; break; + case 2: *(d_uns16*)sch = v; break; + case 4: *(d_uns32*)sch = v; break; + default: assert(0); + } // Add terminating 0 memset((unsigned char *)s + len * sz, 0, sz); @@ -622,7 +641,13 @@ Expression *CatExp::optimize(int result) integer_t v = e1->toInteger(); s = mem.malloc((len + 1) * sz); - memcpy((unsigned char *)s, &v, sz); + switch (sz) + { + case 1: *(d_uns8*)s = v; break; + case 2: *(d_uns16*)s = v; break; + case 4: *(d_uns32*)s = v; break; + default: assert(0); + } memcpy((unsigned char *)s + sz, es2->string, es2->len * sz); // Add terminating 0 diff -uNrp dmd-1.004/src/dmd/parse.c gdc-0.22/d/dmd/parse.c --- dmd-1.004/src/dmd/parse.c 2006-12-29 01:56:46.000000000 +0100 +++ gdc-0.22/d/dmd/parse.c 2007-01-27 17:44:01.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + #include #include @@ -3138,6 +3144,14 @@ Statement *Parser::parseStatement(int fl // Defer parsing of AsmStatements until semantic processing. nextToken(); +#if GDC_EXTENDED_ASM_SYNTAX + if (token.value == TOKlparen) + { + nextToken(); + s = parseExtAsm(1); + break; + } +#endif check(TOKlcurly); toklist = NULL; ptoklist = &toklist; @@ -3191,6 +3205,17 @@ Statement *Parser::parseStatement(int fl error("matching '}' expected, not end of file"); break; + case TOKlparen: + case TOKstring: + // If the first token is a string or '(', parse as extended asm. + if (! toklist) + { + s = parseExtAsm(0); + statements->push(s); + continue; + } + // ...else, drop through. + default: Ldefault: *ptoklist = new Token(); @@ -3226,6 +3251,114 @@ Statement *Parser::parseStatement(int fl return s; } +Statement *Parser::parseExtAsm(int expect_rparen) +{ + Expression * insnTemplate; + Expressions * args = NULL; + Array * argNames = NULL; + Expressions * argConstraints = NULL; + int nOutputArgs = 0; + Expressions * clobbers = NULL; + enum InOut phase = Out; + + insnTemplate = parseExpression(); + if (token.value == TOKrparen || token.value == TOKsemicolon) + goto Ldone; + check(TOKcolon); + while (1) { + Expression * arg = NULL; + Identifier * name = NULL; + Expression * constraint = NULL; + + switch (token.value) + { + case TOKsemicolon: + case TOKrparen: + goto Ldone; + + case TOKcolon: + nextToken(); + goto LnextPhase; + + case TOKeof: + error("unterminated statement"); + + case TOKlbracket: + nextToken(); + if (token.value == TOKidentifier) + { + name = token.ident; + nextToken(); + } + else + error("expected identifier after '['"); + check(TOKrbracket); + // drop through + default: + constraint = parsePrimaryExp(); + if (constraint->op != TOKstring) + error("expected constant string constraint for operand"); + arg = parseAssignExp(); + if (! args) + { + args = new Expressions; + argConstraints = new Expressions; + argNames = new Array; + } + args->push(arg); + argNames->push(name); + argConstraints->push(constraint); + if (phase == Out) + nOutputArgs++; + + if (token.value == TOKcomma) + nextToken(); + break; + } + continue; + LnextPhase: + if (phase == Out) + phase = In; + else + break; + } + + while (1) + { + Expression * clobber; + + switch (token.value) + { + case TOKsemicolon: + case TOKrparen: + goto Ldone; + + case TOKeof: + error("unterminated statement"); + + default: + clobber = parseAssignExp(); + if (clobber->op != TOKstring) + error("expected constant string constraint for clobber name"); + if (! clobbers) + clobbers = new Expressions; + clobbers->push(clobber); + + if (token.value == TOKcomma) + nextToken(); + break; + } + } + Ldone: + if (expect_rparen) + check(TOKrparen); + else + check(TOKsemicolon); + + return new ExtAsmStatement(loc, insnTemplate, args, argNames, + argConstraints, nOutputArgs, clobbers); +} + void Parser::check(enum TOK value) { if (token.value != value) @@ -3762,12 +3895,12 @@ Expression *Parser::parsePrimaryExp() break; case TOKint32v: - e = new IntegerExp(loc, token.int32value, Type::tint32); + e = new IntegerExp(loc, (d_int32)token.int64value, Type::tint32); nextToken(); break; case TOKuns32v: - e = new IntegerExp(loc, token.uns32value, Type::tuns32); + e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tuns32); nextToken(); break; @@ -3827,17 +3960,17 @@ Expression *Parser::parsePrimaryExp() break; case TOKcharv: - e = new IntegerExp(loc, token.uns32value, Type::tchar); + e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tchar); nextToken(); break; case TOKwcharv: - e = new IntegerExp(loc, token.uns32value, Type::twchar); + e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::twchar); nextToken(); break; case TOKdcharv: - e = new IntegerExp(loc, token.uns32value, Type::tdchar); + e = new IntegerExp(loc, (d_uns32)token.uns64value, Type::tdchar); nextToken(); break; diff -uNrp dmd-1.004/src/dmd/parse.h gdc-0.22/d/dmd/parse.h --- dmd-1.004/src/dmd/parse.h 2006-10-26 00:39:32.000000000 +0200 +++ gdc-0.22/d/dmd/parse.h 2007-01-27 17:44:01.000000000 +0100 @@ -84,6 +84,7 @@ struct Parser : Lexer Array *parseDeclarations(); void parseContracts(FuncDeclaration *f); Statement *parseStatement(int flags); + Statement *parseExtAsm(int expect_rparen); Initializer *parseInitializer(); void check(enum TOK value); void check(enum TOK value, char *string); diff -uNrp dmd-1.004/src/dmd/port.h gdc-0.22/d/dmd/port.h --- dmd-1.004/src/dmd/port.h 2004-03-26 23:11:52.000000000 +0100 +++ gdc-0.22/d/dmd/port.h 2006-06-02 05:31:29.000000000 +0200 @@ -13,7 +13,7 @@ #ifndef TYPEDEFS #define TYPEDEFS -#include +//#include #if _MSC_VER typedef __int64 longlong; @@ -45,14 +45,14 @@ struct Port static ulonglong strtoull(const char *p, char **pend, int base); static char *ull_to_string(char *buffer, ulonglong ull); - static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull); + // static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull); // Convert ulonglong to double static double ull_to_double(ulonglong ull); // Get locale-dependent list separator static char *list_separator(); - static wchar_t *wlist_separator(); + // static wchar_t *wlist_separator(); }; #endif diff -uNrp dmd-1.004/src/dmd/root.c gdc-0.22/d/dmd/root.c --- dmd-1.004/src/dmd/root.c 2006-12-01 00:46:32.000000000 +0100 +++ gdc-0.22/d/dmd/root.c 2007-01-27 17:44:01.000000000 +0100 @@ -7,6 +7,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + #include #include #include @@ -14,16 +20,14 @@ #include #include -#if _MSC_VER -#include -#endif +#include "gdc_alloca.h" #if _WIN32 #include #include #endif -#if linux +#ifndef _WIN32 #include #include #include @@ -46,6 +50,7 @@ extern "C" void __cdecl _assert(void *e, } #endif +#ifndef IN_GCC /************************************* * Convert wchar string to ascii string. */ @@ -82,6 +87,7 @@ int wcharIsAscii(wchar_t *us, unsigned l } return 1; } +#endif /*********************************** @@ -117,11 +123,11 @@ void error(const char *format, ...) va_list ap; va_start(ap, format); - printf("Error: "); - vprintf(format, ap); + fprintf(stderr, "Error: "); + vfprintf(stderr, format, ap); va_end( ap ); - printf("\n"); - fflush(stdout); + fprintf(stderr, "\n"); + fflush(stderr); exit(EXIT_FAILURE); } @@ -132,11 +138,11 @@ void error(const dchar *format, ...) va_list ap; va_start(ap, format); - printf("Error: "); - vwprintf(format, ap); + fprintf(stderr, "Error: "); + vfwprintf(stderr, format, ap); va_end( ap ); - printf("\n"); - fflush(stdout); + printf(stderr, "\n"); + fflush(stderr); exit(EXIT_FAILURE); } @@ -156,11 +162,11 @@ void warning(const char *format, ...) va_list ap; va_start(ap, format); - printf("Warning: "); - vprintf(format, ap); + fprintf(stderr, "Warning: "); + vfprintf(stderr, format, ap); va_end( ap ); - printf("\n"); - fflush(stdout); + fprintf(stderr, "\n"); + fflush(stderr); } /****************************** Object ********************************/ @@ -182,7 +188,7 @@ int Object::compare(Object *obj) void Object::print() { - printf("%s %p\n", toChars(), this); + fprintf(stderr, "%s %p\n", toChars(), this); } char *Object::toChars() @@ -300,7 +306,7 @@ char *String::toChars() void String::print() { - printf("String '%s'\n",str); + fprintf(stderr, "String '%s'\n",str); } @@ -322,14 +328,14 @@ char *FileName::combine(char *path, char namelen = strlen(name); f = (char *)mem.malloc(pathlen + 1 + namelen + 1); memcpy(f, path, pathlen); -#if linux +#ifndef _WIN32 if (path[pathlen - 1] != '/') { f[pathlen] = '/'; pathlen++; } #endif #if _WIN32 - if (path[pathlen - 1] != '\\' && path[pathlen - 1] != ':') + if (path[pathlen - 1] != '\\' && path[pathlen - 1] != ':' && path[pathlen - 1] != '/') { f[pathlen] = '\\'; pathlen++; } @@ -376,7 +382,7 @@ Array *FileName::splitPath(const char *p #if _WIN32 case ';': #endif -#if linux +#ifndef _WIN32 case ':': #endif p++; @@ -390,7 +396,7 @@ Array *FileName::splitPath(const char *p case '\r': continue; // ignore carriage returns -#if linux +#ifndef _WIN32 case '~': buf.writestring(getenv("HOME")); continue; @@ -490,7 +496,7 @@ int FileName::absolute(const char *name) (*name == '/') || (*name && name[1] == ':'); #endif -#if linux +#ifndef _WIN32 return (*name == '/'); #endif } @@ -511,11 +517,12 @@ char *FileName::ext(const char *str) switch (*e) { case '.': return e + 1; -#if linux +#ifndef _WIN32 case '/': break; #endif #if _WIN32 + case '/': case '\\': case ':': break; @@ -549,11 +556,12 @@ char *FileName::name(const char *str) { switch (*e) { -#if linux +#ifndef _WIN32 case '/': return e + 1; #endif #if _WIN32 + case '/': case '\\': case ':': return e + 1; @@ -586,12 +594,12 @@ char *FileName::path(const char *str) if (n > str) { -#if linux +#ifndef _WIN32 if (n[-1] == '/') n--; #endif #if _WIN32 - if (n[-1] == '\\') + if (n[-1] == '\\' || n[-1] == '/') n--; #endif } @@ -622,14 +630,14 @@ char *FileName::replaceName(char *path, namelen = strlen(name); f = (char *)mem.malloc(pathlen + 1 + namelen + 1); memcpy(f, path, pathlen); -#if linux +#ifndef _WIN32 if (path[pathlen - 1] != '/') { f[pathlen] = '/'; pathlen++; } #endif #if _WIN32 - if (path[pathlen - 1] != '\\' && path[pathlen - 1] != ':') + if (path[pathlen - 1] != '\\' && path[pathlen - 1] != ':' && path[pathlen - 1] != '/') { f[pathlen] = '\\'; pathlen++; } @@ -698,7 +706,7 @@ int FileName::equalsExt(const char *ext) return 1; if (!e || !ext) return 0; -#if linux +#ifndef _WIN32 return strcmp(e,ext) == 0; #endif #if _WIN32 @@ -717,7 +725,7 @@ void FileName::CopyTo(FileName *to) #if _WIN32 file.touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA)); // keep same file time #endif -#if linux +#ifndef _WIN32 file.touchtime = mem.malloc(sizeof(struct stat)); // keep same file time #endif file.readv(); @@ -759,7 +767,7 @@ char *FileName::searchPath(Array *path, int FileName::exists(const char *name) { -#if linux +#ifndef _WIN32 struct stat st; if (stat(name, &st) < 0) @@ -813,8 +821,7 @@ void FileName::ensurePathExists(const ch //printf("mkdir(%s)\n", path); #if _WIN32 if (mkdir(path)) -#endif -#if linux +#else if (mkdir(path, 0777)) #endif error("cannot create directory %s", path); @@ -870,7 +877,7 @@ void File::mark() int File::read() { -#if linux +#ifndef _WIN32 off_t size; ssize_t numread; int fd; @@ -894,21 +901,21 @@ int File::read() //printf("\tfile opened\n"); if (fstat(fd, &buf)) { - printf("\tfstat error, errno = %d\n",errno); + fprintf(stderr, "\tfstat error, errno = %d\n",errno); goto err2; } size = buf.st_size; buffer = (unsigned char *) mem.malloc(size + 2); if (!buffer) { - printf("\tmalloc error, errno = %d\n",errno); + fprintf(stderr, "\tmalloc error, errno = %d\n",errno); goto err2; } numread = ::read(fd, buffer, size); if (numread != size) { - printf("\tread error, errno = %d\n",errno); + fprintf(stderr, "\tread error, errno = %d\n",errno); goto err2; } @@ -917,7 +924,7 @@ int File::read() if (close(fd) == -1) { - printf("\tclose error, errno = %d\n",errno); + fprintf(stderr, "\tclose error, errno = %d\n",errno); goto err; } @@ -1002,7 +1009,7 @@ err1: int File::mmread() { -#if linux +#ifndef _WIN32 return read(); #endif #if _WIN32 @@ -1056,7 +1063,7 @@ Lerr: int File::write() { -#if linux +#ifndef _WIN32 int fd; ssize_t numwritten; char *name; @@ -1129,7 +1136,7 @@ err: int File::append() { -#if linux +#ifndef _WIN32 return 1; #endif #if _WIN32 @@ -1209,7 +1216,7 @@ void File::appendv() int File::exists() { -#if linux +#ifndef _WIN32 return 0; #endif #if _WIN32 @@ -1234,7 +1241,7 @@ int File::exists() void File::remove() { -#if linux +#ifndef _WIN32 ::remove(this->name->toChars()); #endif #if _WIN32 @@ -1249,7 +1256,7 @@ Array *File::match(char *n) Array *File::match(FileName *n) { -#if linux +#ifndef _WIN32 return NULL; #endif #if _WIN32 @@ -1287,7 +1294,7 @@ Array *File::match(FileName *n) int File::compareTime(File *f) { -#if linux +#ifndef _WIN32 return 0; #endif #if _WIN32 @@ -1301,7 +1308,7 @@ int File::compareTime(File *f) void File::stat() { -#if linux +#ifndef _WIN32 if (!touchtime) { touchtime = mem.calloc(1, sizeof(struct stat)); @@ -1325,7 +1332,7 @@ void File::stat() void File::checkoffset(size_t offset, size_t nbytes) { if (offset > len || offset + nbytes > len) - error("Corrupt file '%s': offset x%zx off end of file",toChars(),offset); + error("Corrupt file '%s': offset x%"PRIxSIZE" off end of file",toChars(),offset); } char *File::toChars() @@ -1396,7 +1403,7 @@ void OutBuffer::writebstring(unsigned ch write(string,*string + 1); } -void OutBuffer::writestring(char *string) +void OutBuffer::writestring(const char *string) { write(string,strlen(string)); } @@ -1554,7 +1561,7 @@ void OutBuffer::writeUTF16(unsigned w) void OutBuffer::write4(unsigned w) { reserve(4); - *(unsigned long *)(this->data + offset) = w; + *(uint32_t *)(this->data + offset) = w; offset += 4; } @@ -1595,19 +1602,21 @@ void OutBuffer::vprintf(const char *form char *p; unsigned psize; int count; + va_list args_copy; p = buffer; psize = sizeof(buffer); for (;;) { + va_copy(args_copy, args); #if _WIN32 - count = _vsnprintf(p,psize,format,args); + count = _vsnprintf(p,psize,format,args_copy); if (count != -1) break; psize *= 2; #endif -#if linux - count = vsnprintf(p,psize,format,args); +#ifndef _WIN32 + count = vsnprintf(p,psize,format,args_copy); if (count == -1) psize *= 2; else if (count >= psize) @@ -1627,19 +1636,20 @@ void OutBuffer::vprintf(const wchar_t *f dchar *p; unsigned psize; int count; + va_list args_copy; p = buffer; psize = sizeof(buffer) / sizeof(buffer[0]); for (;;) { #if _WIN32 - count = _vsnwprintf(p,psize,format,args); + count = _vsnwprintf(p,psize,format,args_copy); if (count != -1) break; psize *= 2; #endif -#if linux - count = vsnwprintf(p,psize,format,args); +#ifndef _WIN32 + count = vsnwprintf(p,psize,format,args_copy); if (count == -1) psize *= 2; else if (count >= psize) diff -uNrp dmd-1.004/src/dmd/root.h gdc-0.22/d/dmd/root.h --- dmd-1.004/src/dmd/root.h 2006-11-21 02:22:14.000000000 +0100 +++ gdc-0.22/d/dmd/root.h 2006-12-17 06:03:04.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + #ifndef ROOT_H #define ROOT_H @@ -29,9 +35,11 @@ int wcharIsAscii(wchar_t *, unsigned len int bstrcmp(unsigned char *s1, unsigned char *s2); char *bstr2str(unsigned char *b); +#ifndef GCC_SAFE_DMD void error(const char *format, ...); void error(const wchar_t *format, ...); void warning(const char *format, ...); +#endif #ifndef TYPEDEFS #define TYPEDEFS @@ -263,7 +271,7 @@ struct OutBuffer : Object void reset(); void write(const void *data, unsigned nbytes); void writebstring(unsigned char *string); - void writestring(char *string); + void writestring(const char *string); void writedstring(const char *string); void writedstring(const wchar_t *string); void prependstring(char *string); diff -uNrp dmd-1.004/src/dmd/scope.c gdc-0.22/d/dmd/scope.c --- dmd-1.004/src/dmd/scope.c 2006-11-21 01:37:06.000000000 +0100 +++ gdc-0.22/d/dmd/scope.c 2007-01-27 17:44:01.000000000 +0100 @@ -7,6 +7,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + #include #include @@ -58,6 +64,7 @@ Scope::Scope() this->protection = PROTpublic; this->explicitProtection = 0; this->stc = 0; + this->attributes = NULL; this->offset = 0; this->inunion = 0; this->incontract = 0; @@ -91,6 +98,7 @@ Scope::Scope(Scope *enclosing) this->protection = enclosing->protection; this->explicitProtection = enclosing->explicitProtection; this->stc = enclosing->stc; + this->attributes = enclosing->attributes; this->offset = 0; this->inunion = enclosing->inunion; this->incontract = enclosing->incontract; diff -uNrp dmd-1.004/src/dmd/scope.h gdc-0.22/d/dmd/scope.h --- dmd-1.004/src/dmd/scope.h 2006-11-21 01:36:34.000000000 +0100 +++ gdc-0.22/d/dmd/scope.h 2007-01-27 17:44:01.000000000 +0100 @@ -7,6 +7,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + #ifndef DMD_SCOPE_H #define DMD_SCOPE_H @@ -71,6 +77,7 @@ struct Scope int explicitProtection; // set if in an explicit protection attribute unsigned stc; // storage class + Expressions * attributes; // GCC decl/type attributes unsigned flags; #define SCOPEctor 1 // constructor type diff -uNrp dmd-1.004/src/dmd/statement.c gdc-0.22/d/dmd/statement.c --- dmd-1.004/src/dmd/statement.c 2006-12-30 17:07:58.000000000 +0100 +++ gdc-0.22/d/dmd/statement.c 2007-01-27 17:44:01.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + #include #include #include @@ -1363,15 +1369,17 @@ Statement *ForeachStatement::semantic(Sc * _aaApply(aggr, keysize, flde) */ if (dim == 2) - fdapply = FuncDeclaration::genCfunc(Type::tindex, "_aaApply2"); + fdapply = FuncDeclaration::genCfunc(Type::tindex, "_aaApply2", + Type::tvoid->arrayOf(), Type::tsize_t, flde->type); // flde->type is not generic else - fdapply = FuncDeclaration::genCfunc(Type::tindex, "_aaApply"); + fdapply = FuncDeclaration::genCfunc(Type::tindex, "_aaApply", + Type::tvoid->arrayOf(), Type::tsize_t, flde->type); // flde->type is not generic); ec = new VarExp(0, fdapply); Expressions *exps = new Expressions(); exps->push(aggr); size_t keysize = taa->key->size(); keysize = (keysize + 3) & ~3; - exps->push(new IntegerExp(0, keysize, Type::tint32)); + exps->push(new IntegerExp(0, keysize, Type::tsize_t)); exps->push(flde); e = new CallExp(loc, ec, exps); e->type = Type::tindex; // don't run semantic() on e @@ -1406,7 +1414,8 @@ Statement *ForeachStatement::semantic(Sc const char *r = (op == TOKforeach_reverse) ? "R" : ""; int j = sprintf(fdname, "_aApply%s%.*s%d", r, 2, fntab[flag], dim); assert(j < sizeof(fdname)); - fdapply = FuncDeclaration::genCfunc(Type::tindex, fdname); + fdapply = FuncDeclaration::genCfunc(Type::tindex, fdname, + Type::tvoid->arrayOf(), flde->type); // flde->type is not generic ec = new VarExp(0, fdapply); Expressions *exps = new Expressions(); @@ -2115,7 +2124,7 @@ DefaultStatement::DefaultStatement(Loc l { this->statement = s; #if IN_GCC -+ cblock = NULL; + cblock = NULL; #endif } diff -uNrp dmd-1.004/src/dmd/statement.h gdc-0.22/d/dmd/statement.h --- dmd-1.004/src/dmd/statement.h 2006-12-18 18:30:26.000000000 +0100 +++ gdc-0.22/d/dmd/statement.h 2007-01-27 17:44:01.000000000 +0100 @@ -707,4 +707,26 @@ struct AsmStatement : Statement void toIR(IRState *irs); }; + +#ifdef IN_GCC + +// Assembler instructions with D expression operands +struct ExtAsmStatement : Statement +{ + Expression *insnTemplate; + Expressions *args; + Array *argNames; // of NULL or Identifier* + Expressions *argConstraints; // of StringExp* + unsigned nOutputArgs; + Expressions *clobbers; // of StringExp* + + ExtAsmStatement(Loc loc, Expression *insnTemplate, Expressions *args, Array *argNames, + Expressions *argConstraints, int nOutputArgs, Expressions *clobbers); + Statement *syntaxCopy(); + Statement *semantic(Scope *sc); + void toIR(IRState *irs); +}; + +#endif + #endif /* DMD_STATEMENT_H */ diff -uNrp dmd-1.004/src/dmd/struct.c gdc-0.22/d/dmd/struct.c --- dmd-1.004/src/dmd/struct.c 2007-01-25 23:47:40.000000000 +0100 +++ gdc-0.22/d/dmd/struct.c 2007-02-03 17:34:12.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + #include #include @@ -40,6 +46,8 @@ AggregateDeclaration::AggregateDeclarati aggNew = NULL; aggDelete = NULL; + attributes = NULL; + stag = NULL; sinit = NULL; scope = NULL; @@ -248,6 +256,9 @@ void StructDeclaration::semantic(Scope * scx = scope; // save so we don't make redundant copies scope = NULL; } +#ifdef IN_GCC + methods.setDim(0); +#endif parent = sc->parent; handle = type->pointerTo(); @@ -256,6 +267,10 @@ void StructDeclaration::semantic(Scope * assert(!isAnonymous()); if (sc->stc & STCabstract) error("structs, unions cannot be abstract"); + if (attributes) + attributes->append(sc->attributes); + else + attributes = sc->attributes; if (sizeok == 0) // if not already done the addMember step { @@ -270,6 +285,7 @@ void StructDeclaration::semantic(Scope * sizeok = 0; sc2 = sc->push(this); sc2->stc = 0; + sc2->attributes = NULL; sc2->parent = this; if (isUnionDeclaration()) sc2->inunion = 1; diff -uNrp dmd-1.004/src/dmd/template.c gdc-0.22/d/dmd/template.c --- dmd-1.004/src/dmd/template.c 2007-01-26 15:36:00.000000000 +0100 +++ gdc-0.22/d/dmd/template.c 2007-02-03 17:34:12.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, December 2006 +*/ + // Handle template implementation #include @@ -1604,7 +1610,7 @@ Lnomatch: void TemplateTypeParameter::print(Object *oarg, Object *oded) { - printf(" %s\n", ident->toChars()); + fprintf(stderr, " %s\n", ident->toChars()); Type *t = isType(oarg); Type *ta = isType(oded); @@ -1612,11 +1618,11 @@ void TemplateTypeParameter::print(Object assert(ta); if (specType) - printf("\tSpecialization: %s\n", specType->toChars()); + fprintf(stderr, "\tSpecialization: %s\n", specType->toChars()); if (defaultType) - printf("\tDefault: %s\n", defaultType->toChars()); - printf("\tArgument: %s\n", t ? t->toChars() : "NULL"); - printf("\tDeduced Type: %s\n", ta->toChars()); + fprintf(stderr, "\tDefault: %s\n", defaultType->toChars()); + fprintf(stderr, "\tArgument: %s\n", t ? t->toChars() : "NULL"); + fprintf(stderr, "\tDeduced Type: %s\n", ta->toChars()); } @@ -1802,12 +1808,12 @@ Lnomatch: void TemplateAliasParameter::print(Object *oarg, Object *oded) { - printf(" %s\n", ident->toChars()); + fprintf(stderr, " %s\n", ident->toChars()); Dsymbol *sa = isDsymbol(oded); assert(sa); - printf("\tArgument alias: %s\n", sa->toChars()); + fprintf(stderr, "\tArgument alias: %s\n", sa->toChars()); } void TemplateAliasParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -2035,13 +2041,13 @@ Lnomatch: void TemplateValueParameter::print(Object *oarg, Object *oded) { - printf(" %s\n", ident->toChars()); + fprintf(stderr, " %s\n", ident->toChars()); Expression *ea = isExpression(oded); if (specValue) - printf("\tSpecialization: %s\n", specValue->toChars()); - printf("\tArgument Value: %s\n", ea ? ea->toChars() : "NULL"); + fprintf(stderr, "\tSpecialization: %s\n", specValue->toChars()); + fprintf(stderr, "\tArgument Value: %s\n", ea ? ea->toChars() : "NULL"); } @@ -2243,6 +2249,9 @@ TemplateInstance::TemplateInstance(Loc l this->semanticdone = 0; this->withsym = NULL; this->nest = 0; +#ifdef IN_GCC + this->objFileModule = NULL; +#endif this->havetempdecl = 0; this->isnested = 0; this->errors = 0; @@ -2265,6 +2274,9 @@ TemplateInstance::TemplateInstance(Loc l this->semanticdone = 0; this->withsym = NULL; this->nest = 0; +#ifdef IN_GCC + this->objFileModule = NULL; +#endif this->havetempdecl = 1; this->isnested = 0; this->errors = 0; @@ -2312,6 +2324,10 @@ void TemplateInstance::addIdent(Identifi idents.push(ident); } +#ifdef IN_GCC +#include "d-dmd-gcc.h" +#endif + void TemplateInstance::semantic(Scope *sc) { if (global.errors) @@ -2328,6 +2344,17 @@ void TemplateInstance::semantic(Scope *s #if LOG printf("\n+TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); #endif +#ifdef IN_GCC + /* + fprintf(stderr, "ti '%s' (%p), belongs in '%s'\n", toChars(), this, + sc->module->toPrettyChars()); + if (inst) { + fprintf(stderr, " -- really '%s' (%p)\n", inst->toChars(), inst); + } else { + fprintf(stderr, " -- doing semantic\n"); + } + */ +#endif if (inst) // if semantic() was already run { #if LOG @@ -2430,11 +2457,45 @@ void TemplateInstance::semantic(Scope *s int dosemantic3 = 0; { Array *a; int i; +#ifdef IN_GCC + /* For "all" and "private" template modes, templates are always + emitted. Problem: This picks up templates that aren't even + needed in the current module. */ + + if (d_gcc_force_templates()) + { + //fprintf(stderr, "\t0: adding to %s %s\n", sc->scopesym->kind(), sc->scopesym->toChars()); + objFileModule = d_gcc_get_output_module(); + a = objFileModule->members; + } + else +#endif if (sc->scopesym && sc->scopesym->members && !sc->scopesym->isTemplateMixin()) { //printf("\t1: adding to %s %s\n", sc->scopesym->kind(), sc->scopesym->toChars()); a = sc->scopesym->members; +#ifdef IN_GCC + { + Dsymbol * p = sc->scopesym; + Module * m; + TemplateInstance * i; + + while (p) { + if ( (i = p->isTemplateInstance()) ) { + if (i->objFileModule) { + objFileModule = i->objFileModule; + break; + } + } else if ( (m = p->isModule()) ) { + objFileModule = m; // %% importedFrom ? + break; + } + p = p->parent; + } + // fprintf(stderr, "\t1: adding %s to module %s via %s %s\n", tempdecl->toChars(), objFileModule?objFileModule->toChars():"", sc->scopesym->kind(), sc->scopesym->toChars()); + } + #endif } else { Module *m = sc->module->importedFrom; @@ -2442,6 +2503,9 @@ void TemplateInstance::semantic(Scope *s a = m->members; if (m->semanticdone >= 3) dosemantic3 = 1; +#ifdef IN_GCC + objFileModule = m; +#endif } for (i = 0; 1; i++) { @@ -2523,10 +2587,12 @@ void TemplateInstance::semantic(Scope *s //printf("isnested = %d, sc->parent = %s\n", isnested, sc->parent->toChars()); sc2->parent = /*isnested ? sc->parent :*/ this; +#ifndef IN_GCC #if _WIN32 __try { #endif +#endif for (int i = 0; i < members->dim; i++) { Dsymbol *s = (Dsymbol *)members->data[i]; @@ -2539,6 +2605,7 @@ void TemplateInstance::semantic(Scope *s //printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); sc2->module->runDeferredSemantic(); } +#ifndef IN_GCC #if _WIN32 } __except (__ehfilter(GetExceptionInformation())) @@ -2548,6 +2615,7 @@ void TemplateInstance::semantic(Scope *s fatal(); } #endif +#endif /* If any of the instantiation members didn't get semantic() run * on them due to forward references, we cannot run semantic2() @@ -2988,7 +3056,7 @@ Identifier *TemplateInstance::genIdent() //printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars()); id = tempdecl->ident->toChars(); - buf.printf("__T%zu%s", strlen(id), id); + buf.printf("__T%"PRIuSIZE"%s", strlen(id), id); args = tiargs; for (int i = 0; i < args->dim; i++) { Object *o = (Object *)args->data[i]; @@ -3054,7 +3122,7 @@ Identifier *TemplateInstance::genIdent() else { char *p = sa->mangle(); - buf.printf("%zu%s", strlen(p), p); + buf.printf("%"PRIuSIZE"%s", strlen(p), p); } } else if (va) diff -uNrp dmd-1.004/src/dmd/tocsym.c gdc-0.22/d/dmd/tocsym.c --- dmd-1.004/src/dmd/tocsym.c 2007-01-15 00:57:18.000000000 +0100 +++ gdc-0.22/d/dmd/tocsym.c 2007-02-03 17:34:12.000000000 +0100 @@ -12,6 +12,7 @@ #include #include #include +#include "gdc_alloca.h" #include "mars.h" #include "module.h" @@ -96,7 +97,7 @@ Symbol *Dsymbol::toSymbolX(const char *p Symbol *Dsymbol::toSymbol() { - printf("Dsymbol::toSymbol() '%s', kind = '%s'\n", toChars(), kind()); + fprintf(stderr, "Dsymbol::toSymbol() '%s', kind = '%s'\n", toChars(), kind()); #ifdef DEBUG halt(); #endif @@ -237,7 +238,7 @@ Symbol *VarDeclaration::toSymbol() break; default: - printf("linkage = %d\n", linkage); + fprintf(stderr, "linkage = %d\n", linkage); assert(0); } type_setmangle(&t, m); @@ -339,7 +340,7 @@ Symbol *FuncDeclaration::toSymbol() break; default: - printf("linkage = %d\n", linkage); + fprintf(stderr, "linkage = %d\n", linkage); assert(0); } } diff -uNrp dmd-1.004/src/dmd/todt.c gdc-0.22/d/dmd/todt.c --- dmd-1.004/src/dmd/todt.c 2007-01-09 00:54:14.000000000 +0100 +++ gdc-0.22/d/dmd/todt.c 2007-02-03 17:34:12.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + /* A dt_t is a simple structure representing data to be added * to the data segment of the output object file. As such, * it is a list of initialized bytes, 0 data, and offsets from @@ -16,12 +22,17 @@ * be written to the data segment. */ +#undef integer_t #include #include #include #include #include +#ifdef __APPLE__ +#define integer_t dmd_integer_t +#endif + #include "lexer.h" #include "mtype.h" #include "expression.h" @@ -32,12 +43,14 @@ // Back end +#ifndef IN_GCC #include "cc.h" #include "el.h" #include "oper.h" #include "global.h" #include "code.h" #include "type.h" +#endif #include "dt.h" extern Symbol *static_sym(); @@ -306,8 +319,6 @@ dt_t *ArrayInitializer::toDtBit() dt_t **pdtend; Type *tb = type->toBasetype(); - //printf("ArrayInitializer::toDtBit('%s')\n", toChars()); - Bits databits; Bits initbits; @@ -368,7 +379,11 @@ dt_t *ArrayInitializer::toDtBit() } d = NULL; +#ifdef IN_GCC + pdtend = dtnbits(&d, databits.allocdim * size, (char *)databits.data, sizeof(databits.data[0])); +#else pdtend = dtnbytes(&d, databits.allocdim * size, (char *)databits.data); +#endif switch (tb->ty) { case Tsarray: @@ -431,6 +446,8 @@ dt_t **Expression::toDt(dt_t **pdt) return pdt; } +#ifndef IN_GCC + dt_t **IntegerExp::toDt(dt_t **pdt) { unsigned sz; @@ -474,7 +491,7 @@ dt_t **RealExp::toDt(dt_t **pdt) break; default: - printf("%s\n", toChars()); + fprintf(stderr, "%s\n", toChars()); type->print(); assert(0); break; @@ -521,6 +538,9 @@ dt_t **ComplexExp::toDt(dt_t **pdt) return pdt; } + +#endif + dt_t **NullExp::toDt(dt_t **pdt) { assert(type); @@ -537,14 +557,22 @@ dt_t **StringExp::toDt(dt_t **pdt) { case Tarray: dtdword(pdt, len); +#ifndef IN_GCC pdt = dtabytes(pdt, TYnptr, 0, (len + 1) * sz, (char *)string); +#else + pdt = dtawords(pdt, len + 1, string, sz); +#endif break; case Tsarray: { TypeSArray *tsa = (TypeSArray *)type; integer_t dim; +#ifndef IN_GCC pdt = dtnbytes(pdt, len * sz, (const char *)string); +#else + pdt = dtnwords(pdt, len, string, sz); +#endif if (tsa->dim) { dim = tsa->dim->toInteger(); @@ -557,11 +585,15 @@ dt_t **StringExp::toDt(dt_t **pdt) break; } case Tpointer: +#ifndef IN_GCC pdt = dtabytes(pdt, TYnptr, 0, (len + 1) * sz, (char *)string); +#else + pdt = dtawords(pdt, len + 1, string, sz); +#endif break; default: - printf("StringExp::toDt(type = %s)\n", type->toChars()); + fprintf(stderr, "StringExp::toDt(type = %s)\n", type->toChars()); assert(0); } return pdt; @@ -722,6 +754,12 @@ void ClassDeclaration::toDt2(dt_t **pdt, void StructDeclaration::toDt(dt_t **pdt) { + if (zeroInit) + { + dtnzeros(pdt, structsize); + return; + } + unsigned offset; unsigned i; dt_t *dt; @@ -812,8 +850,13 @@ dt_t **TypeSArray::toDtElem(dt_t **pdt, databits.resize(len); if (e->toInteger()) databits.set(); +#ifdef IN_GCC + pdt = dtnbits(pdt, databits.allocdim * sizeof(databits.data[0]), + (char *)databits.data, sizeof(databits.data[0])); +#else pdt = dtnbytes(pdt, databits.allocdim * sizeof(databits.data[0]), (char *)databits.data); +#endif } else { diff -uNrp dmd-1.004/src/dmd/toobj.c gdc-0.22/d/dmd/toobj.c --- dmd-1.004/src/dmd/toobj.c 2007-01-26 15:57:54.000000000 +0100 +++ gdc-0.22/d/dmd/toobj.c 2007-02-03 18:35:36.000000000 +0100 @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2004 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com @@ -7,6 +7,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + #include #include #include @@ -26,6 +32,7 @@ #include "template.h" #include +#ifndef IN_GCC #include "cc.h" #include "global.h" #include "oper.h" @@ -35,9 +42,56 @@ #include "cgcv.h" #include "outbuf.h" #include "irstate.h" +#else +#include "dt.h" +#endif + +#ifdef IN_GCC +#include "d-dmd-gcc.h" +#endif void obj_lzext(Symbol *s1,Symbol *s2); +#ifdef IN_GCC +#if 0 +static bool m_in_a(Module * m, Array * a) { + for (unsigned i = 0; i < a->dim; i++) + if ( m == (Module *) a->data[i] ) + return true; + return false; +} +static void find_module_deps(Module * the_module, Array * out_deps) +{ + Array work; + unsigned wi = 0; + + work.push(the_module); + while (wi < work.dim) { + Module * a_module = (Module *) work.data[wi]; + for (unsigned i = 0; i < a_module->aimports.dim; i++) { + Module * an_imp = (Module*) a_module->aimports.data[i]; + if (! an_imp->needModuleInfo() || + m_in_a(an_imp, & work) || m_in_a(an_imp, out_deps)) + continue; + if (an_imp->strictlyneedmoduleinfo) + { + out_deps->push(an_imp); + fprintf(stderr, "idep: %s -> %s", the_module->toPrettyChars(), + an_imp->toPrettyChars()); + if (a_module != the_module) + fprintf(stderr, " (via %s)", a_module->toPrettyChars()); + fprintf(stderr, "\n"); + } + else + work.push(an_imp); + } + wi++; + } +} +#endif +#endif + + /* ================================================================== */ // Put out instance of ModuleInfo for this Module @@ -95,6 +149,18 @@ void Module::genmoduleinfo() // importedModules[] int aimports_dim = aimports.dim; +#ifdef IN_GCC +#if 0 + Array adeps; + + if (! d_gcc_supports_weak()) + { + find_module_deps(this, & adeps); + aimports_dim = adeps.dim; + } + else +#endif +#endif for (i = 0; i < aimports.dim; i++) { Module *m = (Module *)aimports.data[i]; if (!m->needModuleInfo()) @@ -135,6 +201,22 @@ void Module::genmoduleinfo() ////////////////////////////////////////////// +#ifdef IN_GCC +#if 0 + if (! d_gcc_supports_weak()) + for (i = 0; i < adeps.dim; i++) + { + Module *m; + Symbol *s; + + m = (Module *) adeps.data[i]; + s = m->toSymbol(); + s->Sflags |= SFLweak; // doesn't do anything yet, but see d-decls.cc:Module::toSymbol + dtxoff(&dt, s, 0, TYnptr); + } + else +#endif +#endif for (i = 0; i < aimports.dim; i++) { Module *m; @@ -168,13 +250,33 @@ void Module::genmoduleinfo() } /* ================================================================== */ - void Dsymbol::toObjFile() { //printf("Dsymbol::toObjFile('%s')\n", toChars()); // ignore +#ifdef IN_GCC + TupleDeclaration * td = this->isTupleDeclaration(); + if (td) + { + for (unsigned i = 0; i < td->objects->dim; i++) + { + Object * o = (Object *) td->objects->data[i]; + Expression * e; + Dsymbol *ds; + Declaration *d; + if ((o->dyncast() == DYNCAST_EXPRESSION) && + ((Expression *) o)->op == TOKdsymbol) + { + ds = ((DsymbolExp *) o)->s; + d = ds->isDeclaration(); + if (d) + d->toObjFile(); + } + + } + } +#endif } - /* ================================================================== */ void ClassDeclaration::toObjFile() @@ -194,15 +296,10 @@ void ClassDeclaration::toObjFile() assert(!scope); // semantic() should have been run to completion - scclass = SCglobal; - for (Dsymbol *parent = this->parent; parent; parent = parent->parent) - { - if (parent->isTemplateInstance()) - { - scclass = SCcomdat; - break; - } - } + if (parent && parent->isTemplateInstance()) + scclass = SCcomdat; + else + scclass = SCglobal; // Put out the members for (i = 0; i < members->dim; i++) @@ -214,6 +311,7 @@ void ClassDeclaration::toObjFile() } // Build destructor by aggregating dtors[] +#ifndef IN_GCC switch (dtors.dim) { case 0: // No destructors for this class @@ -270,6 +368,9 @@ void ClassDeclaration::toObjFile() writefunc(sdtor); } } +#else + sdtor = d_gcc_aggregate_dtors(this); +#endif // Generate C symbols toSymbol(); @@ -693,15 +794,10 @@ void InterfaceDeclaration::toObjFile() if (global.params.symdebug) toDebug(); - scclass = SCglobal; - for (Dsymbol *parent = this->parent; parent; parent = parent->parent) - { - if (parent->isTemplateInstance()) - { - scclass = SCcomdat; - break; - } - } + if (parent && parent->isTemplateInstance()) + scclass = SCcomdat; + else + scclass = SCglobal; // Put out the members for (i = 0; i < members->dim; i++) @@ -959,6 +1055,7 @@ void VarDeclaration::toObjFile() if (tb->next->toBasetype()->ty == Tbit) { integer_t value; +#ifndef IN_GCC value = ie->exp->toInteger(); value = (value & 1) ? ~(integer_t)0 : (integer_t)0; if (value == 0) @@ -978,6 +1075,18 @@ void VarDeclaration::toObjFile() dtnbytes(&s->Sdt, 4, (char *)&value); } } +#else + + s->Sdt = NULL; + if (ie->exp->toInteger()) { + Bits databits; + databits.resize(dim); + databits.set(); + dtnbits(& s->Sdt, databits.allocdim * sizeof(databits.data[0]), (char *)databits.data, sizeof(databits.data[0])); + } else { + dtnzeros(&s->Sdt, ((unsigned)dim + 31) / 32 * 4); + } +#endif } else { @@ -1026,6 +1135,15 @@ void VarDeclaration::toObjFile() obj_export(s,0); } } +#ifdef IN_GCC + else { + // This is needed for VarDeclarations in mixins that are to be + // local variables of a function. Otherwise, it would be + // enough to make a check for isVarDeclaration() in + // DeclarationExp::toElem. + d_gcc_emit_local_variable(this); + } +#endif } /* ================================================================== */ @@ -1061,7 +1179,8 @@ void TypedefDeclaration::toObjFile() #if ELFOBJ // Burton sinit->Sseg = CDATA; #endif /* ELFOBJ */ - sinit->Sdt = tc->sym->init->toDt(); + if (! sinit->Sdt) + sinit->Sdt = tc->sym->init->toDt(); outdata(sinit); } } diff -uNrp dmd-1.004/src/dmd/total.h gdc-0.22/d/dmd/total.h --- dmd-1.004/src/dmd/total.h 2006-10-05 16:04:10.000000000 +0200 +++ gdc-0.22/d/dmd/total.h 2006-12-17 06:03:04.000000000 +0100 @@ -19,7 +19,7 @@ #include #include #include -#include +//#include #include "root.h" #include "stringtable.h" diff -uNrp dmd-1.004/src/dmd/typinf.c gdc-0.22/d/dmd/typinf.c --- dmd-1.004/src/dmd/typinf.c 2007-01-23 19:23:04.000000000 +0100 +++ gdc-0.22/d/dmd/typinf.c 2007-02-03 17:34:12.000000000 +0100 @@ -8,6 +8,12 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + #include #include @@ -28,6 +34,7 @@ #include "aggregate.h" #include +#ifndef IN_GCC #include "cc.h" #include "global.h" #include "oper.h" @@ -37,6 +44,11 @@ #include "cgcv.h" #include "outbuf.h" #include "irstate.h" +#else +#include "symbol.h" +#include "dt.h" +#include "d-dmd-gcc.h" +#endif extern Symbol *static_sym(); @@ -686,7 +698,11 @@ Expression *createTypeInfoArray(Scope *s buf.writeByte(0); id = Lexer::idPool((char *)buf.data); +#ifdef IN_GCC + Module *m = d_gcc_get_output_module(); +#else Module *m = sc->module; +#endif Dsymbol *s = m->symtab->lookup(id); if (s && s->parent == m) diff -uNrp dmd-1.004/src/phobos/acinclude.m4 gdc-0.22/d/phobos/acinclude.m4 --- dmd-1.004/src/phobos/acinclude.m4 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/acinclude.m4 2007-01-27 17:44:01.000000000 +0100 @@ -0,0 +1,253 @@ +dnl Unix-specific configuration +AC_DEFUN(DPHOBOS_CONFIGURE_UNIX,[ + +AC_CHECK_HEADERS(pthread.h,:, + [AC_MSG_ERROR([can't find pthread.h. Pthreads is the only supported thread library.])]) + +AC_MSG_CHECKING([for recursive mutex name]) +AC_TRY_COMPILE([#include ],[ +pthread_mutexattr_t attr; +pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);], + [AC_DEFINE(HAVE_PTHREAD_MUTEX_RECURSIVE,1,[Determines how to declared recursive mutexes]) + AC_MSG_RESULT([PTHREAD_MUTEX_RECURSIVE])], + [AC_MSG_RESULT([PTHREAD_MUTEX_RECURSIVE_NP])]) + +AC_CHECK_TYPES([pthread_barrier_t, pthread_barrierattr_t, + pthread_rwlock_t, pthread_rwlockattr_t, + pthread_spinlock_t],,,[#include ]) + +AC_CHECK_TYPES([clockid_t],,,[#include ]) + +dnl -pthread doesn't work because, by putting it in specs, it is passed +dnl to the linker instead of being interpreted by the driver... +dnl -lc_r ins't quite right because there is also a -lc_r_p +# -pthread + +if test -z "$d_thread_lib"; then + AC_MSG_CHECKING([for thread library linker argument]) + d_thread_lib=error + for thrd_lib in "" -lc_r -lpthread -ldce; do + d_savelibs=$LIBS + LIBS="$LIBS $thrd_lib" + + AC_TRY_LINK([#include ],[ + pthread_create(0,0,0,0);], + [d_thread_lib=$thrd_lib], + :) + + LIBS=$d_savelibs + + if test "$d_thread_lib" != "error"; then + break + fi + done + case "$d_thread_lib" in + error) AC_MSG_ERROR([Not found! You may need to use --enable-thread-lib]) ;; + -*) AC_MSG_RESULT([$d_thread_lib]) ;; + *) AC_MSG_RESULT([none needed]) ;; + esac +fi +LIBS="$LIBS $d_thread_lib" + +dnl BSD socket configuration + +AC_CHECK_TYPES([socklen_t, siginfo_t],[],[],[ +#include +#include +#include ]) + +AC_MSG_CHECKING([for sa_len]) +AC_TRY_COMPILE([ +#include +#include ],[ +struct sockaddr s; s.sa_len = 0;], + [AC_MSG_RESULT([yes]) + DCFG_SA_LEN=GNU_BsdSockets_salen], + [AC_MSG_RESULT([no]) + DCFG_SA_LEN=""]) + +if test -n "$DCFG_SA_LEN"; then + AC_MSG_CHECKING([size of sa_len]) + AC_TRY_COMPILE([ +#include +#include ],[ + struct sockaddr s; + struct Test { + int x: sizeof(s.sa_len)==1; + };], + [AC_MSG_RESULT([one byte])], + [AC_MSG_RESULT([not one byte]) + AC_MSG_ERROR([Can not handle layout of sockaddr. Please report this so your system can be supported.])]) +else + AC_MSG_CHECKING([size of sa_family]) + AC_TRY_COMPILE([ +#include +#include ],[ + struct sockaddr s; + struct Test { + int x: sizeof(s.sa_family)==2; + };], + [AC_MSG_RESULT([two bytes])], + [AC_MSG_RESULT([not two bytes]) + AC_MSG_ERROR([Can not handle layout of sockaddr. Please report this so your system can be supported.])]) +fi + +AC_SEARCH_LIBS(sem_init, pthread rt posix4) + +DCFG_PTHREAD_SUSPEND= +AC_SUBST(DCFG_PTHREAD_SUSPEND) + +if true; then + AC_CHECK_HEADERS(semaphore.h) + AC_CHECK_FUNC(sem_init) + AC_CHECK_FUNC(semaphore_create) + AC_CHECK_FUNC(pthread_cond_wait) + + if test -z "$d_sem_impl"; then + # Probably need to test what actually works. sem_init is defined + # on AIX and Darwin but does not actually work. + # For now, test for Mach semaphores first so it overrides Posix. AIX + # is a special case. + if test "$ac_cv_func_semaphore_create" = "yes"; then + d_sem_impl="mach" + elif test "$ac_cv_func_sem_init" = "yes" && \ + test "$ac_cv_header_semaphore_h" = "yes" && \ + test -z "$d_is_aix"; then + d_sem_impl="posix" + elif test "$ac_cv_func_pthread_cond_wait" = "yes"; then + d_sem_impl="pthreads" + fi + fi + + dnl TODO: change this to using pthreads? if so, define usepthreads + dnl and configure semaphore + + case "$d_sem_impl" in + posix) DCFG_SEMAPHORE_IMPL="GNU_Semaphore_POSIX" ;; + mach) DCFG_SEMAPHORE_IMPL="GNU_Semaphore_Mach" + d_module_mach=1 ;; + pthreads) DCFG_SEMAPHORE_IMPL="GNU_Sempahore_Pthreads" ;; + skyos) DCFG_SEMAPHORE_IMPL="GNU_Sempahore_Pthreads" + D_EXTRA_OBJS="$D_EXTRA_OBJS std/c/skyos/compat.o" + ;; + *) AC_MSG_ERROR([No usable semaphore implementation]) ;; + esac +else + dnl Need to be able to query thread state for this method to be useful + AC_CHECK_FUNC(pthread_suspend_np) + AC_CHECK_FUNC(pthread_continue_np) + + if test "$ac_cv_func_pthread_suspend_np" = "yes" && \ + test "$ac_cv_func_pthread_continue_np" = "yes" ; then + # TODO: need to test that these actually work. + DCFG_PTHREAD_SUSPEND=GNU_pthread_suspend + else + AC_MSG_ERROR([TODO]) + fi +fi + +AC_DEFINE(PHOBOS_USE_PTHREADS,1,[Define if using pthreads]) + +AC_CHECK_FUNC(mmap,DCFG_MMAP="GNU_Unix_Have_MMap",[]) + +AC_CHECK_FUNC(getpwnam_r,DCFG_GETPWNAM_R="GNU_Unix_Have_getpwnam_r",[]) + + +D_EXTRA_OBJS="gcc/configunix.o gcc/cbridge_fdset.o std/c/unix/unix.o $D_EXTRA_OBJS" +# Add "linux" module for compatibility even if not Linux +D_EXTRA_OBJS="std/c/linux/linux.o $D_EXTRA_OBJS" +D_PREREQ_SRCS="$D_PREREQ_SRCS "'$(configunix_d_src)' +DCFG_UNIX="Unix" + +]) + +dnl Garbage collection configuration +AC_DEFUN(DPHOBOS_CONFIGURE_GC, [ + +D_GC_MODULES=internal/gc/gcgcc.o + +d_gc_alloc= +d_gc_stack= +d_gc_data= + +case "$d_target_os" in + aix*) d_gc_data="$d_gc_data GC_Use_Data_Fixed" + ;; + cygwin*) d_gc_data="$d_gc_data GC_Use_Data_Fixed" + ;; + darwin*) D_GC_MODULES="$D_GC_MODULES internal/gc/gc_dyld.o" + d_gc_stack=GC_Use_Stack_Fixed + d_gc_data="$d_gc_data GC_Use_Data_Dyld" + ;; + freebsd*) D_GC_MODULES="$D_GC_MODULES internal/gc/gc_freebsd.o" + d_gc_stack=GC_Use_Stack_FreeBSD + d_gc_data="$d_gc_data GC_Use_Data_Fixed" + dnl maybe just GC_Use_Stack_ExternC + ;; + linux*) + #d_gc_stack=GC_Use_Stack_Proc_Stat + d_gc_data="$d_gc_data GC_Use_Data_Fixed" + #have_proc_maps=1 + ;; + skyos*) d_gc_data="$d_gc_data GC_Use_Data_Fixed" + ;; + *) D_GC_MODULES=internal/gc/gcgcc.o + ;; +esac + +if test -z "$d_gc_alloc"; then + AC_CHECK_FUNC(mmap,d_gc_alloc=GC_Use_Alloc_MMap,[]) +fi +if test -z "$d_gc_alloc"; then + AC_CHECK_FUNC(valloc,d_gc_alloc=GC_Use_Alloc_Valloc,[]) +fi +if test -z "$d_gc_alloc"; then + # Use malloc as a fallback + d_gc_alloc=GC_Use_Alloc_Malloc +fi +#if test -z "$d_gc_alloc"; then +# AC_MSG_ERROR([No usable memory allocation routine]) +#fi + +if test -z "$d_gc_stack"; then + AC_MSG_CHECKING([for __libc_stack_end]) + AC_TRY_LINK([],[ + extern long __libc_stack_end; + return __libc_stack_end == 0;], + [AC_MSG_RESULT(yes) + d_gc_stack=GC_Use_Stack_GLibC], + [AC_MSG_RESULT(no)]) +fi +if test -z "$d_gc_stack"; then + d_gc_stack=GC_Use_Stack_Guess + D_GC_MODULES="$D_GC_MODULES internal/gc/gc_guess_stack.o" +fi +if test -z "$d_gc_stack"; then + AC_MSG_ERROR([No usable stack origin information]) +fi + +dnl if test -z "$d_gc_data"; then +dnl AC_MSG_CHECKING([for __data_start and _end]) +dnl AC_TRY_LINK([],[ +dnl extern int __data_start; +dnl extern int _end; +dnl return & _end - & __data_start;], +dnl [AC_MSG_RESULT(yes) +dnl d_gc_data="$d_gc_data GC_Use_Data_Data_Start_End"], +dnl [AC_MSG_RESULT(no)]) +dnl fi +if test -n "$have_proc_maps" && test "$enable_proc_maps" = auto; then + enable_proc_maps=yes +fi +if test "$enable_proc_maps" = yes; then + d_gc_data="$d_gc_data GC_Use_Data_Proc_Maps" +fi +if test -z "$d_gc_data"; then + AC_MSG_ERROR([No usable data segment information]) +fi + +f="-fversion=$d_gc_alloc -fversion=$d_gc_stack" +for m in $d_gc_data; do f="$f -fversion=$m"; done +D_GC_FLAGS=$f + +]) diff -uNrp dmd-1.004/src/phobos/aclocal.m4 gdc-0.22/d/phobos/aclocal.m4 --- dmd-1.004/src/phobos/aclocal.m4 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/aclocal.m4 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,14 @@ +# generated automatically by aclocal 1.9.5 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_include([acinclude.m4]) diff -uNrp dmd-1.004/src/phobos/etc/c/zlib.d gdc-0.22/d/phobos/etc/c/zlib.d --- dmd-1.004/src/phobos/etc/c/zlib.d 2007-01-26 22:58:42.000000000 +0100 +++ gdc-0.22/d/phobos/etc/c/zlib.d 2006-12-17 06:03:04.000000000 +0100 @@ -1,12 +1,11 @@ /* zlib.d: modified from zlib.h by Walter Bright */ -/* updated from 1.2.1 to 1.2.3 by Thomas Kuehne */ module etc.c.zlib; /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.3, July 18th, 2005 + version 1.2.1, November 17th, 2003 - Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -35,8 +34,7 @@ module etc.c.zlib; extern (C): -char[] ZLIB_VERSION = "1.2.3"; -const ZLIB_VERNUM = 0x1230; +char[] ZLIB_VERSION = "1.2.1"; /* The 'zlib' compression library provides in-memory compression and @@ -51,22 +49,24 @@ const ZLIB_VERNUM = 0x1230; application must provide more input and/or consume the output (providing more output space) before each call. - The compressed data format used by default by the in-memory functions is - the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped - around a deflate stream, which is itself documented in RFC 1951. + The compressed data format used by the in-memory functions is the zlib + format, which is a zlib wrapper documented in RFC 1950, wrapped around a + deflate stream, which is itself documented in RFC 1951. The library also supports reading and writing files in gzip (.gz) format with an interface similar to that of stdio using the functions that start with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - This library can optionally read and write gzip streams in memory as well. - The zlib format was designed to be compact and fast for use in memory and on communications channels. The gzip format was designed for single- file compression on file systems, has a larger header than zlib to maintain directory information, and uses a different, slower check method than zlib. + This library does not provide any functions to write gzip files in memory. + However such functions could be easily written using zlib's deflate function, + the documentation in the gzip RFC, and the examples in gzio.c. + The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash even in case of corrupted input. @@ -92,7 +92,7 @@ struct z_stream free_func zfree; /* used to free the internal state */ void* opaque; /* private data object passed to zalloc and zfree */ - int data_type; /* best guess about the data type: binary or text */ + int data_type; /* best guess about the data type: ascii or binary */ uint adler; /* adler32 value of the uncompressed data */ uint reserved; /* reserved for future use */ } @@ -100,30 +100,7 @@ struct z_stream alias z_stream* z_streamp; /* - gzip header information passed to and from zlib routines. See RFC 1952 - for more details on the meanings of these fields. -*/ -struct gz_header { - int text; /* true if compressed data believed to be text */ - ulong time; /* modification time */ - int xflags; /* extra flags (not used when writing a gzip file) */ - int os; /* operating system */ - byte *extra; /* pointer to extra field or Z_NULL if none */ - uint extra_len; /* extra field length (valid if extra != Z_NULL) */ - uint extra_max; /* space at extra (only when reading header) */ - byte *name; /* pointer to zero-terminated file name or Z_NULL */ - uint name_max; /* space at name (only when reading header) */ - byte *comment; /* pointer to zero-terminated comment or Z_NULL */ - uint comm_max; /* space at comment (only when reading header) */ - int hcrc; /* true if there was or will be a header crc */ - int done; /* true when done reading gzip header (not used - when writing a gzip file) */ -} - -alias gz_header* gz_headerp; - -/* - The application must update next_in and avail_in when avail_in has + The application must update next_in and avail_in when avail_in has dropped to zero. It must update next_out and avail_out when avail_out has dropped to zero. The application must initialize zalloc, zfree and opaque before calling the init function. All other fields are set by the @@ -197,7 +174,6 @@ enum Z_FILTERED = 1, Z_HUFFMAN_ONLY = 2, Z_RLE = 3, - Z_FIXED = 4, Z_DEFAULT_STRATEGY = 0, } /* compression strategy; see deflateInit2() below for details */ @@ -205,10 +181,8 @@ enum enum { Z_BINARY = 0, - Z_TEXT = 1, + Z_ASCII = 1, Z_UNKNOWN = 2, - - Z_ASCII = Z_TEXT } /* Possible values of the data_type field (though see inflate()) */ @@ -284,10 +258,6 @@ int deflate(z_streamp strm, int flush); and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. - Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to - decide how much data to accumualte before producing output, in order to - maximize compression. - If the parameter flush is set to Z_SYNC_FLUSH, all pending output is flushed to the output buffer and the output is aligned on a byte boundary, so that the decompressor can get all input data available so far. (In particular @@ -299,7 +269,7 @@ int deflate(z_streamp strm, int flush); Z_SYNC_FLUSH, and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - compression. + the compression. If deflate returns with avail_out == 0, this function must be called again with the same value of the flush parameter and more output space (updated @@ -324,8 +294,8 @@ int deflate(z_streamp strm, int flush); deflate() sets strm->adler to the adler32 checksum of all input read so far (that is, total_in bytes). - deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered binary. This field is only for information purposes and does not affect the compression algorithm in any manner. @@ -409,11 +379,11 @@ int inflate(z_streamp strm, int flush); The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much output as possible to the output buffer. Z_BLOCK requests that inflate() stop - if and when it gets to the next deflate block boundary. When decoding the - zlib or gzip format, this will cause inflate() to return immediately after - the header and before the first block. When doing a raw inflate, inflate() - will go ahead and process the first block, and will return when it gets to - the end of that block, or when it runs out of data. + if and when it get to the next deflate block boundary. When decoding the zlib + or gzip format, this will cause inflate() to return immediately after the + header and before the first block. When doing a raw inflate, inflate() will + go ahead and process the first block, and will return when it gets to the end + of that block, or when it runs out of data. The Z_BLOCK option assists in appending to or combining deflate streams. Also to assist in this, on return inflate() will set strm->data_type to the @@ -445,7 +415,7 @@ int inflate(z_streamp strm, int flush); because Z_BLOCK is used. If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the adler32 checksum of the dictionary + below), inflate sets strm-adler to the adler32 checksum of the dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise it sets strm->adler to the adler32 checksum of all output produced so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described @@ -525,8 +495,7 @@ int deflateInit2(z_streamp strm, 16 to windowBits to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper. The gzip header will have no file name, no extra data, no comment, no modification time (set to zero), - no header crc, and the operating system will be set to 255 (unknown). If a - gzip stream is being written, strm->adler is a crc32 instead of an adler32. + no header crc, and the operating system will be set to 255 (unknown). The memLevel parameter specifies how much memory should be allocated for the internal compression state. memLevel=1 uses minimum memory but @@ -545,9 +514,7 @@ int deflateInit2(z_streamp strm, Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy parameter only affects the compression ratio but not the correctness of the - compressed output even if it is not set appropriately. Z_FIXED prevents the - use of dynamic Huffman codes, allowing for a simpler decoder for special - applications. + compressed output even if it is not set appropriately. deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid @@ -574,9 +541,7 @@ int deflateSetDictionary(z_streamp strm, deflateInit or deflateInit2, a part of the dictionary may in effect be discarded, for example if the dictionary is larger than the window size in deflate or deflate2. Thus the strings most likely to be useful should be - put at the end of the dictionary, not at the front. In addition, the - current implementation of deflate will use at most the window size minus - 262 bytes of the provided dictionary. + put at the end of the dictionary, not at the front. Upon return of this function, strm->adler is set to the adler32 value of the dictionary; the decompressor may later use this value to determine @@ -620,59 +585,6 @@ int deflateReset(z_streamp strm); stream state was inconsistent (such as zalloc or state being NULL). */ -int inflatePrime(z_streamp strm, int bits, int value); -/* - This function inserts bits in the inflate input stream. The intent is - that this function is used to start inflating at a bit position in the - middle of a byte. The provided bits will be used before any bytes are used - from next_in. This function should only be used with raw inflate, and - should be used before the first inflate() call after inflateInit2() or - inflateReset(). bits must be less than or equal to 16, and that many of the - least significant bits of value will be inserted in the input. - - inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -int inflateGetHeader(z_streamp strm, gz_headerp head); -/* - inflateGetHeader() requests that gzip header information be stored in the - provided gz_header structure. inflateGetHeader() may be called after - inflateInit2() or inflateReset(), and before the first call of inflate(). - As inflate() processes the gzip stream, head->done is zero until the header - is completed, at which time head->done is set to one. If a zlib stream is - being decoded, then head->done is set to -1 to indicate that there will be - no gzip header information forthcoming. Note that Z_BLOCK can be used to - force inflate() to return immediately after header processing is complete - and before any actual data is decompressed. - - The text, time, xflags, and os fields are filled in with the gzip header - contents. hcrc is set to true if there is a header CRC. (The header CRC - was valid if done is set to one.) If extra is not Z_NULL, then extra_max - contains the maximum number of bytes to write to extra. Once done is true, - extra_len contains the actual extra field length, and extra contains the - extra field, or that field truncated if extra_max is less than extra_len. - If name is not Z_NULL, then up to name_max characters are written there, - terminated with a zero unless the length is greater than name_max. If - comment is not Z_NULL, then up to comm_max characters are written there, - terminated with a zero unless the length is greater than comm_max. When - any of extra, name, or comment are not Z_NULL and the respective field is - not present in the header, then that field is set to Z_NULL to signal its - absence. This allows the use of deflateSetHeader() with the returned - structure to duplicate the header. However if those fields are set to - allocated memory, then the application will need to save those pointers - elsewhere so that they can be eventually freed. - - If inflateGetHeader is not used, then the header information is simply - discarded. The header is always checked for validity, including the header - CRC if present. inflateReset() will reset the process to discard the header - information. The application would need to call inflateGetHeader() again to - retrieve the header from the next gzip stream. - - inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - int deflateParams(z_streamp strm, int level, int strategy); /* Dynamically update the compression level and compression strategy. The @@ -692,21 +604,7 @@ int deflateParams(z_streamp strm, int le if strm->avail_out was zero. */ -int deflateTune(z_streamp strm, int good_length, int max_lazy, int nice_length, - int max_chain); -/* - Fine tune deflate's internal compression parameters. This should only be - used by someone who understands the algorithm used by zlib's deflate for - searching for the best matching string, and even then only by the most - fanatic optimizer trying to squeeze out the last compressed bit for their - specific input data. Read the deflate.c source code for the meaning of the - max_lazy, good_length, nice_length, and max_chain parameters. - - deflateTune() can be called after deflateInit() or deflateInit2(), and - returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. - */ - -int deflateBound(z_streamp strm, uint sourceLen); +uint deflateBound(z_streamp strm, uint sourceLen); /* deflateBound() returns an upper bound on the compressed size after deflation of sourceLen bytes. It must be called after deflateInit() @@ -728,29 +626,6 @@ int deflatePrime(z_streamp strm, int bit stream state was inconsistent. */ -int deflateSetHeader(z_streamp strm, gz_headerp head); -/* - deflateSetHeader() provides gzip header information for when a gzip - stream is requested by deflateInit2(). deflateSetHeader() may be called - after deflateInit2() or deflateReset() and before the first call of - deflate(). The text, time, os, extra field, name, and comment information - in the provided gz_header structure are written to the gzip header (xflag is - ignored -- the extra flags are set according to the compression level). The - caller must assure that, if not Z_NULL, name and comment are terminated with - a zero byte, and that if extra is not Z_NULL, that extra_len bytes are - available there. If hcrc is true, a gzip header crc is included. Note that - the current versions of the command-line version of gzip (up through version - 1.3.x) do not support header crc's, and will report that it is a "multi-part - gzip file" and give up. - - If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). - - deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - int inflateInit2(z_streamp strm, int windowBits) { return inflateInit2_(strm, windowBits, ZLIB_VERSION.ptr, z_stream.sizeof); @@ -784,28 +659,24 @@ int inflateInit2(z_streamp strm, int win windowBits can also be greater than 15 for optional gzip decoding. Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection, or add 16 to decode only the gzip format (the zlib format will - return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is - a crc32 instead of an adler32. + return a Z_DATA_ERROR). inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg - is set to null if there is no error message. inflateInit2 does not perform - any decompression apart from reading the zlib header if present: this will - be done by inflate(). (So next_in and avail_in may be modified, but next_out - and avail_out are unchanged.) -/ + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ int inflateSetDictionary(z_streamp strm, ubyte* dictionary, uint dictLength); /* Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate, - if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the adler32 value returned by that call of inflate. - The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called - immediately after inflateInit2() or inflateReset() and before any call of - inflate() to set the dictionary. The application must insure that the - dictionary that was used for compression is provided. + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (such as NULL dictionary) or the stream state is @@ -1231,12 +1102,6 @@ int gzeof(gzFile file); input stream, otherwise zero. */ -int gzdirect(gzFile file); -/* - Returns 1 if file is being read directly without decompression, otherwise - zero. -*/ - int gzclose(gzFile file); /* Flushes all pending output if necessary, closes the compressed file @@ -1285,20 +1150,12 @@ void gzclearerr (gzFile file); if (adler != original_adler) error(); */ -uint adler32_combine(uint adler1, uint adler2, z_off_t len2); -/* - Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 - and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for - each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. -*/ - uint crc32(uint crc, ubyte *buf, uint len); /* - Update a running CRC-32 with the bytes buf[0..len-1] and return the - updated CRC-32. If buf is NULL, this function returns the required initial - value for the for the crc. Pre- and post-conditioning (one's complement) is - performed within this function so it shouldn't be done by the application. + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. Usage example: uint crc = crc32(0L, Z_NULL, 0); @@ -1309,16 +1166,6 @@ uint crc32(uint crc, ubyte *buf, uint le if (crc != original_crc) error(); */ -uint crc32_combine (uint crc1, uint crc2, z_off_t len2); - -/* - Combine two CRC-32 check values into one. For two sequences of bytes, - seq1 and seq2 with lengths len1 and len2, CRC-32 check values were - calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 - check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and - len2. -*/ - /* various hacks, don't look :) */ diff -uNrp dmd-1.004/src/phobos/etc/gamma.d gdc-0.22/d/phobos/etc/gamma.d --- dmd-1.004/src/phobos/etc/gamma.d 2007-01-26 22:58:42.000000000 +0100 +++ gdc-0.22/d/phobos/etc/gamma.d 2006-12-17 06:03:04.000000000 +0100 @@ -1,8 +1,3 @@ -/* - * Cephes code Copyright 1994 by Stephen L. Moshier - * Converted to D by Don Clugston. - */ - /** Macros: GAMMA = Γ @@ -10,71 +5,93 @@ Macros: */ module etc.gamma; -import std.math; +private import std.math; private import std.stdio; -//import etc.realtest; //------------------------------------------------------------------ const real SQRT2PI = 2.50662827463100050242E0L; // sqrt(2pi) -const real MAXGAMMA = 1755.455L; // exp(tgamma(x)) == inf if x>MAXGAMMA +// exp(tgamma(x)) == inf if x>MAXGAMMA +const real MAXGAMMA = 1755.455L; // Polynomial approximations for gamma and loggamma. static real GammaNumeratorCoeffs[] = [ - 0x1p+0, // 1 - 0x1.acf42d903366539ep-1, // 0.83780043015731267283 - 0x1.73a991c8475f1aeap-2, // 0.36295154366402391688 - 0x1.c7e918751d6b2a92p-4, // 0.1113062816019361559 - 0x1.86d162cca32cfe86p-6, // 0.023853632434611082525 - 0x1.0c378e2e6eaf7cd8p-8, // 0.0040926668283940355009 - 0x1.dc5c66b7d05feb54p-12, // 0.00045429319606080091555 - 0x1.616457b47e448694p-15 // 4.2127604874716220134e-05 + 0x1p+0, // 1 + 0x1.acf42d903366539ep-1, // 0.83780043015731267283 + 0x1.73a991c8475f1aeap-2, // 0.36295154366402391688 + 0x1.c7e918751d6b2a92p-4, // 0.1113062816019361559 + 0x1.86d162cca32cfe86p-6, // 0.023853632434611082525 + 0x1.0c378e2e6eaf7cd8p-8, // 0.0040926668283940355009 + 0x1.dc5c66b7d05feb54p-12, // 0.00045429319606080091555 + 0x1.616457b47e448694p-15 // 4.2127604874716220134e-05 ]; static real GammaDenominatorCoeffs[] = [ - 0x1p+0, // 1 - 0x1.a8f9faae5d8fc8b0p-2, // 0.41501609505884554346 - -0x1.cb7895a6756eebdep-3, // -0.22435109056703291645 - -0x1.7b9bab006d30652ap-5, // -0.046338876712445342138 - 0x1.c671af78f312082ep-6, // 0.027737065658400729792 - -0x1.a11ebbfaf96252dcp-11, // -0.00079559336824947383209 - -0x1.447b4d2230a77ddap-10, // -0.0012377992466531522311 - 0x1.ec1d45bb85e06696p-13, // 0.00023465840591606352443 - -0x1.d4ce24d05bd0a8e6p-17 // -1.3971485174761704409e-05 + 0x1p+0, // 1 + 0x1.a8f9faae5d8fc8bp-2, // 0.41501609505884554346 + -0x1.cb7895a6756eebdep-3, // -0.22435109056703291645 + -0x1.7b9bab006d30652ap-5, // -0.046338876712445342138 + 0x1.c671af78f312082ep-6, // 0.027737065658400729792 + -0x1.a11ebbfaf96252dcp-11, // -0.00079559336824947383209 + -0x1.447b4d2230a77ddap-10, // -0.0012377992466531522311 + 0x1.ec1d45bb85e06696p-13, // 0.00023465840591606352443 + -0x1.d4ce24d05bd0a8e6p-17 // -1.3971485174761704409e-05 +]; + +static real SmallStirlingCoeffs[] = [ + 0x1.55555555555543aap-4, // 0.083333333333333318004 + 0x1.c71c71c720dd8792p-9, // 0.0034722222222300753277 + -0x1.5f7268f0b5907438p-9, // -0.0026813271618763044182 + -0x1.e13cd410e0477de6p-13, // -0.00022947197478731854057 + 0x1.9b0f31643442616ep-11, // 0.00078403348427447530038 + 0x1.2527623a3472ae08p-14, // 6.9893322606231931717e-05 + -0x1.37f6bc8ef8b374dep-11, // -0.00059502375540563301557 + -0x1.8c968886052b872ap-16, // -2.3638488095017590616e-05 + 0x1.76baa9c6d3eeddbcp-11 // 0.0007147391378143610789 +]; + +static real LargeStirlingCoeffs[] = [ + 1.0L, + 8.33333333333333333333E-2L, + 3.47222222222222222222E-3L, + -2.68132716049382716049E-3L, + -2.29472093621399176955E-4L, + 7.84039221720066627474E-4L, + 6.97281375836585777429E-5L ]; static real GammaSmallCoeffs[] = [ - 0x1p+0, // 1 - 0x1.2788cfc6fb618f52p-1, // 0.57721566490153286082 + 0x1p+0, // 1 + 0x1.2788cfc6fb618f52p-1, // 0.57721566490153286082 -0x1.4fcf4026afa2f7ecp-1, // -0.65587807152025406846 -0x1.5815e8fa24d7e306p-5, // -0.042002635034033440541 - 0x1.5512320aea2ad71ap-3, // 0.16653861137208052067 - -0x1.59af0fb9d82e2160p-5, // -0.042197733607059154702 + 0x1.5512320aea2ad71ap-3, // 0.16653861137208052067 + -0x1.59af0fb9d82e216p-5, // -0.042197733607059154702 -0x1.3b4b61d3bfdf244ap-7, // -0.0096220233604062716456 - 0x1.d9358e9d9d69fd34p-8, // 0.0072205994780369096722 + 0x1.d9358e9d9d69fd34p-8, // 0.0072205994780369096722 -0x1.38fc4bcbada775d6p-10 // -0.0011939450513815100956 ]; static real GammaSmallNegCoeffs[] = [ - -0x1p+0, // -1 - 0x1.2788cfc6fb618f54p-1, // 0.57721566490153286086 - 0x1.4fcf4026afa2bc4cp-1, // 0.65587807152025365473 + -0x1p+0, // -1 + 0x1.2788cfc6fb618f54p-1, // 0.57721566490153286086 + 0x1.4fcf4026afa2bc4cp-1, // 0.65587807152025365473 -0x1.5815e8fa2468fec8p-5, // -0.042002635034021129105 -0x1.5512320baedaf4b6p-3, // -0.16653861139444135193 -0x1.59af0fa283baf07ep-5, // -0.042197733437311917216 - 0x1.3b4a70de31e05942p-7, // 0.0096219111550359767339 - 0x1.d9398be3bad13136p-8, // 0.0072208372618931703258 - 0x1.291b73ee05bcbba2p-10 // 0.001133374167243894382 + 0x1.3b4a70de31e05942p-7, // 0.0096219111550359767339 + 0x1.d9398be3bad13136p-8, // 0.0072208372618931703258 + 0x1.291b73ee05bcbba2p-10 // 0.001133374167243894382 ]; static real logGammaStirlingCoeffs[] = [ - 0x1.5555555555553f98p-4, // 0.083333333333333314473 - -0x1.6c16c16c07509b10p-9, // -0.0027777777777503496034 - 0x1.a01a012461cbf1e4p-11, // 0.00079365077958550707556 - -0x1.3813089d3f9d1640p-11, // -0.00059523458517656885149 - 0x1.b911a92555a277b8p-11, // 0.00084127232973224980805 + 0x1.5555555555553f98p-4, // 0.083333333333333314473 + -0x1.6c16c16c07509b1p-9, // -0.0027777777777503496034 + 0x1.a01a012461cbf1e4p-11, // 0.00079365077958550707556 + -0x1.3813089d3f9d164p-11, // -0.00059523458517656885149 + 0x1.b911a92555a277b8p-11, // 0.00084127232973224980805 -0x1.ed0a7b4206087b22p-10, // -0.0018808019381193769072 - 0x1.402523859811b308p-8 // 0.0048850261424322707812 + 0x1.402523859811b308p-8 // 0.0048850261424322707812 ]; static real logGammaNumerator[] = [ @@ -95,58 +112,34 @@ static real logGammaDenominator[] = [ -0x1.301303b99a614a0ap+19, // -622744.11640662195015 -0x1.09e76ab41ae965p+15, // -34035.708405343046707 -0x1.00f95ced9e5f54eep+9, // -513.94814844353701437 - 0x1p+0 // 1 + 0x1p+0 // 1 ]; -/* **************************************************** - * Helper function: Gamma function computed by Stirling's formula. - * - * Stirling's formula for the gamma function is: - * - * $(GAMMA)(x) = sqrt(2 π) xx-0.5 exp(-x) (1 + 1/x P(1/x)) - * - */ -private real gammaStirling(real x) +/* +Helper function: Gamma function computed by Stirling's formula. + +Stirling's formula for the gamma function is: + +$(GAMMA)(x) = sqrt(2 π) xx-0.5 exp(-x) (1 + 1/x P(1/x)) + +*/ +real gammaStirling(real x) { - static real SmallStirlingCoeffs[] = [ - 0x1.55555555555543aap-4, // 0.083333333333333318004 - 0x1.c71c71c720dd8792p-9, // 0.0034722222222300753277 - -0x1.5f7268f0b5907438p-9, // -0.0026813271618763044182 - -0x1.e13cd410e0477de6p-13, // -0.00022947197478731854057 - 0x1.9b0f31643442616ep-11, // 0.00078403348427447530038 - 0x1.2527623a3472ae08p-14, // 6.9893322606231931717e-05 - -0x1.37f6bc8ef8b374dep-11, // -0.00059502375540563301557 - -0x1.8c968886052b872ap-16, // -2.3638488095017590616e-05 - 0x1.76baa9c6d3eeddbcp-11 // 0.0007147391378143610789 - ]; - - static real LargeStirlingCoeffs[] = [ - 1.0L, - 8.33333333333333333333E-2L, - 3.47222222222222222222E-3L, - -2.68132716049382716049E-3L, - -2.29472093621399176955E-4L, - 7.84039221720066627474E-4L, - 6.97281375836585777429E-5L - ]; - - real w = 1.0L / x; - real y = exp(x); - if (x > 1024.0L) - { - // For large x, use rational coefficients from the analytical expansion. - w = poly(w, LargeStirlingCoeffs); - // Avoid overflow in pow() - real v = pow( x, 0.5L * x - 0.25L ); - y = v * (v / y); - } - else - { - w = 1.0L + w * poly(w, SmallStirlingCoeffs); - y = pow( x, x - 0.5L ) / y; - } - y = SQRT2PI * y * w; - return y; + real w = 1.0L/x; + real y = exp(x); + if ( x > 1024.0L ) { + // For large x, use rational coefficients from the analytical expansion. + w = poly(w, LargeStirlingCoeffs); + // Avoid overflow in pow() + real v = pow( x, 0.5L * x - 0.25L ); + y = v * (v / y); + } + else { + w = 1.0L + w * poly( w, SmallStirlingCoeffs); + y = pow( x, x - 0.5L ) / y; + } + y = SQRT2PI * y * w; + return y; } /***************************************************** @@ -177,125 +170,106 @@ private real gammaStirling(real x) */ real tgamma(real x) { - /* Author: Don Clugston. Based on code from the CEPHES library. - * - * Arguments |x| <= 13 are reduced by recurrence and the function - * approximated by a rational function of degree 7/8 in the - * interval (2,3). Large arguments are handled by Stirling's - * formula. Large negative arguments are made positive using - * a reflection formula. - */ - - real q, z; - - if (isnan(x)) - return x; - if (x == -x.infinity) - return real.nan; - if ( fabs(x) > MAXGAMMA ) - return real.infinity; - if (x == 0) - return 1.0 / x; // +- infinity depending on sign of x, create an exception. - - q = fabs(x); - - if ( q > 13.0L ) - { - // Large arguments are handled by Stirling's - // formula. Large negative arguments are made positive using - // the reflection formula. +/* Author: Don Clugston. Based on code from the CEPHES library. + * + * Arguments |x| <= 13 are reduced by recurrence and the function + * approximated by a rational function of degree 7/8 in the + * interval (2,3). Large arguments are handled by Stirling's + * formula. Large negative arguments are made positive using + * a reflection formula. + */ + + real q, z; + if (isnan(x)) return x; + if (x==-x.infinity) return real.nan; + if ( fabs(x) > MAXGAMMA ) return real.infinity; + if (x==0) return 1.0/x; // +- infinity depending on sign of x, create an exception. + + q = fabs(x); + + if ( q > 13.0L ) { + // Large arguments are handled by Stirling's + // formula. Large negative arguments are made positive using + // the reflection formula. + + if ( x < 0.0L ) { + int sgngam = 1; // sign of gamma. + real p = floor(q); + if ( p == q ) return real.nan; // poles for all integers <0. + int intpart = cast(int)(p); + if ( (intpart & 1) == 0 ) + sgngam = -1; + z = q - p; + if ( z > 0.5L ) { + p += 1.0L; + z = q - p; + } + z = q * sin( PI * z ); + z = fabs(z) * gammaStirling(q); + if ( z <= PI/real.max ) return sgngam * real.infinity; + return sgngam * PI/z; + } else { + return gammaStirling(x); + } + } + + // Arguments |x| <= 13 are reduced by recurrence and the function + // approximated by a rational function of degree 7/8 in the + // interval (2,3). - if ( x < 0.0L ) - { - int sgngam = 1; // sign of gamma. - real p = floor(q); - if ( p == q ) - return real.nan; // poles for all integers <0. - int intpart = cast(int)(p); - if ( (intpart & 1) == 0 ) - sgngam = -1; - z = q - p; - if ( z > 0.5L ) - { - p += 1.0L; - z = q - p; - } - z = q * sin( PI * z ); - z = fabs(z) * gammaStirling(q); - if ( z <= PI / real.max ) - return sgngam * real.infinity; - return sgngam * PI / z; - } - else - return gammaStirling(x); - } - - // Arguments |x| <= 13 are reduced by recurrence and the function - // approximated by a rational function of degree 7/8 in the - // interval (2,3). - - z = 1.0L; - while ( x >= 3.0L ) - { - x -= 1.0L; - z *= x; - } - - while ( x < -0.03125L ) - { - z /= x; - x += 1.0L; - } - - if ( x <= 0.03125L ) - { - if ( x == 0.0L ) - return real.nan; - else if ( x < 0.0L ) - { - x = -x; - return z / (x * poly( x, GammaSmallNegCoeffs )); + z = 1.0L; + while ( x >= 3.0L ) { + x -= 1.0L; + z *= x; } - else - { - return z / (x * poly( x, GammaSmallCoeffs )); + + while ( x < -0.03125L ) { + z /= x; + x += 1.0L; + } + + if ( x <= 0.03125L ) { + if ( x == 0.0L ) return real.nan; + else { + if ( x < 0.0L ) { + x = -x; + return z / (x * poly( x, GammaSmallNegCoeffs )); + } else { + return z / (x * poly( x, GammaSmallCoeffs )); + } + } + } + + while ( x < 2.0L ) { + z /= x; + x += 1.0L; } - } - - while ( x < 2.0L ) - { - z /= x; - x += 1.0L; - } - if ( x == 2.0L ) - return z; - - x -= 2.0L; - return z * poly( x, GammaNumeratorCoeffs ) / poly( x, GammaDenominatorCoeffs ); + if ( x == 2.0L ) return z; + + x -= 2.0L; + return z * poly( x, GammaNumeratorCoeffs ) / poly( x, GammaDenominatorCoeffs ); } -unittest -{ - // gamma(n) = factorial(n-1) if n is an integer. - double fact = 1.0L; - for (int i = 1; fact < real.max; ++i) - { - // Require exact equality for small factorials - if (i < 14) - assert(tgamma(i * 1.0L)==fact); - assert(feqrel(tgamma(i * 1.0L), fact) > real.mant_dig - 15); - //writefln(i, " %a ---> %a %a ", i*1.0L, tgamma(i * 1.0L), fact, feqrel(tgamma(i*1.0L), fact)); - fact *= (i * 1.0L); - } - assert(tgamma(0.0) == real.infinity); - assert(tgamma(-0.0) == -real.infinity); - assert(isnan(tgamma(-1.0))); - assert(isnan(tgamma(real.nan))); - assert(tgamma(real.infinity) == real.infinity); - assert(isnan(tgamma(-real.infinity))); - assert(tgamma(real.min * real.epsilon) == real.infinity); - - assert(feqrel(tgamma(0.5), sqrt(PI)) > real.mant_dig - 3); +version(X86) // requires feqrel +unittest { + // gamma(n) = factorial(n-1) if n is an integer. + double fact=1.0L; + for (int i=1; factreal.mant_dig-15); + //writefln(i, " %a ---> %a %a ", i*1.0L, tgamma(i*1.0L), fact, feqrel(tgamma(i*1.0L), fact)); + fact*=(i*1.0L); + } + assert(tgamma(0.0)==real.infinity); + assert(tgamma(-0.0)==-real.infinity); + assert(isnan(tgamma(-1.0))); + assert(isnan(tgamma(real.nan))); + assert(tgamma(real.infinity)==real.infinity); + assert(isnan(tgamma(-real.infinity))); + assert(tgamma(real.min*real.epsilon)==real.infinity); + + assert(feqrel(tgamma(0.5),sqrt(PI))>real.mant_dig-3); } /***************************************************** @@ -318,160 +292,221 @@ unittest */ real lgamma(real x) { - /* Author: Don Clugston. Based on code from the CEPHES library. - * - * For arguments greater than 33, the logarithm of the gamma - * function is approximated by the logarithmic version of - * Stirling's formula using a polynomial approximation of - * degree 4. Arguments between -33 and +33 are reduced by - * recurrence to the interval [2,3] of a rational approximation. - * The cosecant reflection formula is employed for arguments - * less than -33. - */ - real q, w, z, f, nx; - - if (isnan(x)) - return x; - if (fabs(x) == x.infinity) - return x.infinity; - - if ( x < -34.0L ) - { - q = -x; - w = lgamma(q); - real p = floor(q); - if ( p == q ) - return real.infinity; - int intpart = cast(int)(p); - real sgngam = 1; - if ( (intpart & 1) == 0 ) - sgngam = -1; - z = q - p; - if ( z > 0.5L ) - { - p += 1.0L; - z = p - q; + /* Author: Don Clugston. Based on code from the CEPHES library. + * + * For arguments greater than 33, the logarithm of the gamma + * function is approximated by the logarithmic version of + * Stirling's formula using a polynomial approximation of + * degree 4. Arguments between -33 and +33 are reduced by + * recurrence to the interval [2,3] of a rational approximation. + * The cosecant reflection formula is employed for arguments + * less than -33. + */ + real p, q, w, z, f, nx; + + if (isnan(x)) return x; + if (fabs(x)==x.infinity) return x.infinity; + + if( x < -34.0L ) { + q = -x; + w = lgamma(q); + real p = floor(q); + if ( p == q ) return real.infinity; + int intpart = cast(int)(p); + real sgngam = 1; + if ( (intpart & 1) == 0 ) + sgngam = -1; + z = q - p; + if ( z > 0.5L ) { + p += 1.0L; + z = p - q; + } + z = q * sin( PI * z ); + if ( z == 0.0L ) return sgngam * real.infinity; + /* z = LOGPI - logl( z ) - w; */ + z = log( PI/z ) - w; + return( z ); } - z = q * sin( PI * z ); - if ( z == 0.0L ) - return sgngam * real.infinity; - /* z = LOGPI - logl( z ) - w; */ - z = log( PI / z ) - w; - return z; - } - if ( x < 13.0L ) - { - z = 1.0L; - nx = floor( x + 0.5L ); - f = x - nx; - while ( x >= 3.0L ) - { - nx -= 1.0L; - x = nx + f; - z *= x; - } - while ( x < 2.0L ) - { - if( fabs(x) <= 0.03125 ) - { - if ( x == 0.0L ) - return real.infinity; - if ( x < 0.0L ) - { - x = -x; - q = z / (x * poly( x, GammaSmallNegCoeffs)); + if( x < 13.0L ) { + z = 1.0L; + nx = floor( x + 0.5L ); + f = x - nx; + while ( x >= 3.0L ) { + nx -= 1.0L; + x = nx + f; + z *= x; } - else - q = z / (x * poly( x, GammaSmallCoeffs)); - return log( fabs(q) ); - } - z /= nx + f; - nx += 1.0L; - x = nx + f; - } - z = fabs(z); - if ( x == 2.0L ) - return log(z); - x = (nx - 2.0L) + f; - real p = x * poly( x, logGammaNumerator ) / poly( x, logGammaDenominator); - return ( log(z) + p ); - } - + while ( x < 2.0L ) { + if( fabs(x) <= 0.03125 ) { + if ( x == 0.0L ) return real.infinity; + if ( x < 0.0L ) { + x = -x; + q = z / (x * poly( x, GammaSmallNegCoeffs)); + } else + q = z / (x * poly( x, GammaSmallCoeffs)); + return log( fabs(q) ); + } + z /= nx + f; + nx += 1.0L; + x = nx + f; + } + z = fabs(z); + if ( x == 2.0L ) + return log(z); + x = (nx - 2.0L) + f; + p = x * poly( x, logGammaNumerator ) / poly( x, logGammaDenominator); + return ( log(z) + p ); + } + //const real MAXLGM = 1.04848146839019521116e+4928L; - //if ( x > MAXLGM ) return sgngaml * real.infinity; + // if( x > MAXLGM ) return sgngaml * real.infinity; - /* log( sqrt( 2*pi ) ) */ - const real LOGSQRT2PI = 0.91893853320467274178L; - - q = ( x - 0.5L ) * log(x) - x + LOGSQRT2PI; - if (x > 1.0e10L) return q; - real p = 1.0L/(x*x); - q += poly( p, logGammaStirlingCoeffs ) / x; - return q ; + /* log( sqrt( 2*pi ) ) */ + const real LOGSQRT2PI = 0.91893853320467274178L; + + q = ( x - 0.5L ) * log(x) - x + LOGSQRT2PI; + if (x > 1.0e10L) return q; + p = 1.0L/(x*x); + q += poly( p, logGammaStirlingCoeffs ) / x; + return q ; } -unittest -{ - assert(isnan(lgamma(real.nan))); - assert(lgamma(real.infinity) == real.infinity); - assert(lgamma(-1.0) == real.infinity); - assert(lgamma(0.0) == real.infinity); - assert(std.math.isPosZero(lgamma(1.0L))); - assert(std.math.isPosZero(lgamma(2.0L))); +version(X86) // requires feqrel +unittest { + assert(isnan(lgamma(real.nan))); + assert(lgamma(real.infinity)==real.infinity); + assert(lgamma(-1.0)==real.infinity); + assert(lgamma(0.0)==real.infinity); + assert(isPosZero(lgamma(1.0L))); + assert(isPosZero(lgamma(2.0L))); - // x, correct loggamma(x), correct d/dx loggamma(x). - static real[] testpoints = - [ - 8.0L, 8.525146484375L + 1.48766904143001655310E-5, 2.01564147795560999654E0L, - 8.99993896484375e-1L, 6.6375732421875e-2L + 5.11505711292524166220E-6L, -7.54938684259372234258E-1, - 7.31597900390625e-1L, 2.2369384765625e-1 + 5.21506341809849792422E-6L, -1.13355566660398608343E0L, - 2.31639862060546875e-1L, 1.3686676025390625L + 1.12609441752996145670E-5L, -4.56670961813812679012E0, - 1.73162841796875L, -8.88214111328125e-2L + 3.36207740803753034508E-6L, 2.33339034686200586920E-1L, - 1.23162841796875L, -9.3902587890625e-2L + 1.28765089229009648104E-5L, -2.49677345775751390414E-1L, - 7.3786976294838206464e19L, 3.301798506038663053312e21L - 1.656137564136932662487046269677E5L, + // x, correct loggamma(x), correct d/dx loggamma(x). + static real[] testpoints = [ + 8.0L, 8.525146484375L + 1.48766904143001655310E-5, 2.01564147795560999654E0L, + 8.99993896484375e-1L, 6.6375732421875e-2L + 5.11505711292524166220E-6L, -7.54938684259372234258E-1, + 7.31597900390625e-1L, 2.2369384765625e-1 + 5.21506341809849792422E-6L, -1.13355566660398608343E0L, + 2.31639862060546875e-1L, 1.3686676025390625L + 1.12609441752996145670E-5L, -4.56670961813812679012E0, + 1.73162841796875L, -8.88214111328125e-2L + 3.36207740803753034508E-6L, 2.33339034686200586920E-1L, + 1.23162841796875L, -9.3902587890625e-2L + 1.28765089229009648104E-5L, -2.49677345775751390414E-1L, + 7.3786976294838206464e19L, 3.301798506038663053312e21L - 1.656137564136932662487046269677E5L, 4.57477139169563904215E1L, - 1.08420217248550443401E-19L, 4.36682586669921875e1L + 1.37082843669932230418E-5L, + 1.08420217248550443401E-19L, 4.36682586669921875e1L + 1.37082843669932230418E-5L, -9.22337203685477580858E18L, -// 1.0L, 0.0L, -5.77215664901532860607E-1L, -// 2.0L, 0.0L, 4.22784335098467139393E-1L, - -0.5L, 1.2655029296875L + 9.19379714539648894580E-6L, 3.64899739785765205590E-2L, - -1.5L, 8.6004638671875e-1L + 6.28657731014510932682E-7L, 7.03156640645243187226E-1L, - -2.5L, -5.6243896484375E-2L + 1.79986700949327405470E-7, 1.10315664064524318723E0L, - -3.5L, -1.30902099609375L + 1.43111007079536392848E-5L, 1.38887092635952890151E0L - ]; - - // TODO: test derivatives as well. - - for (int i=0; i real.mant_dig-5); - } - - static real logabsgamma(real x) - { - // For poles, tgamma(x) returns nan, but lgamma() returns infinity. - if (x < 0 && x == floor(x)) - return real.infinity; - return log(fabs(tgamma(x))); - } - - static real exploggamma(real x) - { - return exp(lgamma(x)); - } - - static real absgamma(real x) - { - if (x < 0 && x == floor(x)) - return real.infinity; - return fabs(tgamma(x)); - } - - // Check that loggamma(x) = log(gamma(x)) provided x is not -1, -2, -3, ... - //assert(consistencyTwoFuncs(&lgamma, &logabsgamma, -1000, 1700) > real.mant_dig-7); - //assert(consistencyTwoFuncs(&exploggamma, &absgamma, -2000, real.infinity) > real.mant_dig-16); +// 1.0L, 0.0L, -5.77215664901532860607E-1L, +// 2.0L, 0.0L, 4.22784335098467139393E-1L, + -0.5L, 1.2655029296875L + 9.19379714539648894580E-6L, 3.64899739785765205590E-2L, + -1.5L, 8.6004638671875e-1L + 6.28657731014510932682E-7L, 7.03156640645243187226E-1L, + -2.5L, -5.6243896484375E-2L + 1.79986700949327405470E-7, 1.10315664064524318723E0L, + -3.5L, -1.30902099609375L + 1.43111007079536392848E-5L, 1.38887092635952890151E0L + ]; + // TODO: test derivatives as well. + for (int i=0; i real.mant_dig-5); + } + + static real logabsgamma(real x) + { + // For poles, tgamma(x) returns nan, but lgamma() returns infinity. + if (x<0 && x==floor(x)) return real.infinity; + return log(fabs(tgamma(x))); + } + static real exploggamma(real x) + { + return exp(lgamma(x)); + } + static real absgamma(real x) + { + if (x<0 && x==floor(x)) return real.infinity; + return fabs(tgamma(x)); + } + + // Check that loggamma(x) = log(gamma(x)) provided x is not -1, -2, -3, ... + //assert(consistencyTwoFuncs(&lgamma, &logabsgamma, -1000, 1700) > real.mant_dig-7); + //assert(consistencyTwoFuncs(&exploggamma, &absgamma, -2000, real.infinity) > real.mant_dig-16); } +/** + Test the consistency of a real function which can be calculated in two ways. + + Returns the worst (minimum) value of feqrel(firstfunc(x), secondfunc(x)) + for all x in the domain. +Params: + firstfunc, secondfunc Functions to be compared + domain A sequence of pairs of numbers giving the first and last +points which are valid for the function. +eg. (-real.infinity, real.infinity) ==> valid everywhere + (-real.infinity, -real.min, real.min, real.infinity) ==> valid for x!=0. + Returns: + number of bits for which firstfunc(x) and secondfunc(x) are equal for + every point x in the domain. + -1 = at least one point is wrong by a factor of 2 or more. +*/ +version(X86) // requires feqrel +int consistencyTwoFuncs(real function (real) firstfunc, + real function (real) secondfunc, real [] domain ...) +{ + /* Author: Don Clugston. License: Public Domain + */ + assert(domain.length>=2); // must have at least one valid range + assert((domain.length & 1) == 0); // must have even number of endpoints. + + int worsterror=real.mant_dig+1; + real worstx=domain[0]; // where does the biggest discrepancy occur? + + void testPoint(real x) { + for (int i=0; i=domain[i] && x<=domain[i+1]) { + int u=feqrel(secondfunc(x), firstfunc(x)); + if (u 1) { @@ -110,7 +116,7 @@ extern (C) long _adReverseChar(char[] a) hi = hi - 1 + (stridehi - stridelo); } } - return *cast(long*)(&a); + return *cast(Array*)(&a); } unittest @@ -146,7 +152,7 @@ unittest * reversed. */ -extern (C) long _adReverseWchar(wchar[] a) +extern (C) Array _adReverseWchar(wchar[] a) { if (a.length > 1) { @@ -204,7 +210,7 @@ extern (C) long _adReverseWchar(wchar[] hi = hi - 1 + (stridehi - stridelo); } } - return *cast(long*)(&a); + return *cast(Array*)(&a); } unittest @@ -224,15 +230,163 @@ unittest assert(r == "c\U00012345ba"); } +// %% Had to move _adCmpChar to the beginning of the file +// due to a extern/static symbol conflict on darwin... +/*************************************** + * Support for array compare test. + */ + +extern (C) int _adCmpChar(Array a1, Array a2) +{ +version (Asm86) +{ + asm + { naked ; + + push EDI ; + push ESI ; + + mov ESI,a1+4[4+ESP] ; + mov EDI,a2+4[4+ESP] ; + + mov ECX,a1[4+ESP] ; + mov EDX,a2[4+ESP] ; + + cmp ECX,EDX ; + jb GotLength ; + + mov ECX,EDX ; + +GotLength: + cmp ECX,4 ; + jb DoBytes ; + + // Do alignment if neither is dword aligned + test ESI,3 ; + jz Aligned ; + + test EDI,3 ; + jz Aligned ; +DoAlign: + mov AL,[ESI] ; //align ESI to dword bounds + mov DL,[EDI] ; + + cmp AL,DL ; + jnz Unequal ; + + inc ESI ; + inc EDI ; + + test ESI,3 ; + + lea ECX,[ECX-1] ; + jnz DoAlign ; +Aligned: + mov EAX,ECX ; + + // do multiple of 4 bytes at a time + + shr ECX,2 ; + jz TryOdd ; + + repe ; + cmpsd ; + + jnz UnequalQuad ; + +TryOdd: + mov ECX,EAX ; +DoBytes: + // if still equal and not end of string, do up to 3 bytes slightly + // slower. + + and ECX,3 ; + jz Equal ; + + repe ; + cmpsb ; + + jnz Unequal ; +Equal: + mov EAX,a1[4+ESP] ; + mov EDX,a2[4+ESP] ; + + sub EAX,EDX ; + pop ESI ; + + pop EDI ; + ret ; + +UnequalQuad: + mov EDX,[EDI-4] ; + mov EAX,[ESI-4] ; + + cmp AL,DL ; + jnz Unequal ; + + cmp AH,DH ; + jnz Unequal ; + + shr EAX,16 ; + + shr EDX,16 ; + + cmp AL,DL ; + jnz Unequal ; + + cmp AH,DH ; +Unequal: + sbb EAX,EAX ; + pop ESI ; + + or EAX,1 ; + pop EDI ; + + ret ; + } +} +else +{ + int len; + int c; + + //printf("adCmpChar()\n"); + len = a1.length; + if (a2.length < len) + len = a2.length; + c = std.string.memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len); + if (!c) + c = cast(int)a1.length - cast(int)a2.length; + return c; +} +} + +unittest +{ + debug(adi) printf("array.CmpChar unittest\n"); + + char[] a = "hello"; + + assert(a > "hel"); + assert(a >= "hel"); + assert(a < "helloo"); + assert(a <= "helloo"); + assert(a > "betty"); + assert(a >= "betty"); + assert(a == "hello"); + assert(a <= "hello"); + assert(a >= "hello"); +} + /********************************************** * Support for array.reverse property. */ -extern (C) long _adReverse(Array a, int szelem) +extern (C) Array _adReverse(Array a, int szelem) out (result) { - assert(result is *cast(long*)(&a)); + assert(result is a); } body { @@ -271,7 +425,7 @@ extern (C) long _adReverse(Array a, int //delete tmp; } } - return *cast(long*)(&a); + return a; } unittest @@ -363,7 +517,7 @@ unittest * Sort array of chars. */ -extern (C) long _adSortChar(char[] a) +extern (C) char[] _adSortChar(char[] a) { if (a.length > 1) { @@ -378,14 +532,14 @@ extern (C) long _adSortChar(char[] a) } delete da; } - return *cast(long*)(&a); + return a; } /********************************************** * Sort array of wchars. */ -extern (C) long _adSortWchar(wchar[] a) +extern (C) wchar[] _adSortWchar(wchar[] a) { if (a.length > 1) { @@ -400,7 +554,7 @@ extern (C) long _adSortWchar(wchar[] a) } delete da; } - return *cast(long*)(&a); + return a; } /********************************************** @@ -510,12 +664,12 @@ unittest version (none) { extern (C) int _adEqBit(Array a1, Array a2) -{ size_t i; +{ int i; if (a1.length != a2.length) return 0; // not equal - auto p1 = cast(byte*)a1.ptr; - auto p2 = cast(byte*)a2.ptr; + auto p1 = cast(ubyte*)a1.ptr; + auto p2 = cast(ubyte*)a2.ptr; auto n = a1.length / 8; for (i = 0; i < n; i++) { @@ -599,151 +753,6 @@ unittest assert(a >= "hello"); } -/*************************************** - * Support for array compare test. - */ - -extern (C) int _adCmpChar(Array a1, Array a2) -{ -version (X86) -{ - asm - { naked ; - - push EDI ; - push ESI ; - - mov ESI,a1+4[4+ESP] ; - mov EDI,a2+4[4+ESP] ; - - mov ECX,a1[4+ESP] ; - mov EDX,a2[4+ESP] ; - - cmp ECX,EDX ; - jb GotLength ; - - mov ECX,EDX ; - -GotLength: - cmp ECX,4 ; - jb DoBytes ; - - // Do alignment if neither is dword aligned - test ESI,3 ; - jz Aligned ; - - test EDI,3 ; - jz Aligned ; -DoAlign: - mov AL,[ESI] ; //align ESI to dword bounds - mov DL,[EDI] ; - - cmp AL,DL ; - jnz Unequal ; - - inc ESI ; - inc EDI ; - - test ESI,3 ; - - lea ECX,[ECX-1] ; - jnz DoAlign ; -Aligned: - mov EAX,ECX ; - - // do multiple of 4 bytes at a time - - shr ECX,2 ; - jz TryOdd ; - - repe ; - cmpsd ; - - jnz UnequalQuad ; - -TryOdd: - mov ECX,EAX ; -DoBytes: - // if still equal and not end of string, do up to 3 bytes slightly - // slower. - - and ECX,3 ; - jz Equal ; - - repe ; - cmpsb ; - - jnz Unequal ; -Equal: - mov EAX,a1[4+ESP] ; - mov EDX,a2[4+ESP] ; - - sub EAX,EDX ; - pop ESI ; - - pop EDI ; - ret ; - -UnequalQuad: - mov EDX,[EDI-4] ; - mov EAX,[ESI-4] ; - - cmp AL,DL ; - jnz Unequal ; - - cmp AH,DH ; - jnz Unequal ; - - shr EAX,16 ; - - shr EDX,16 ; - - cmp AL,DL ; - jnz Unequal ; - - cmp AH,DH ; -Unequal: - sbb EAX,EAX ; - pop ESI ; - - or EAX,1 ; - pop EDI ; - - ret ; - } -} -else -{ - int len; - int c; - - //printf("adCmpChar()\n"); - len = a1.length; - if (a2.length < len) - len = a2.length; - c = string.memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len); - if (!c) - c = cast(int)a1.length - cast(int)a2.length; - return c; -} -} - -unittest -{ - debug(adi) printf("array.CmpChar unittest\n"); - - char[] a = "hello"; - - assert(a > "hel"); - assert(a >= "hel"); - assert(a < "helloo"); - assert(a <= "helloo"); - assert(a > "betty"); - assert(a >= "betty"); - assert(a == "hello"); - assert(a <= "hello"); - assert(a >= "hello"); -} /*************************************** * Support for array compare test. diff -uNrp dmd-1.004/src/phobos/internal/arraycat.d gdc-0.22/d/phobos/internal/arraycat.d --- dmd-1.004/src/phobos/internal/arraycat.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/internal/arraycat.d 2007-02-03 17:34:12.000000000 +0100 @@ -25,6 +25,12 @@ * distribution. */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, November 2006 +*/ + module arraycat; import object; diff -uNrp dmd-1.004/src/phobos/internal/cmain.d gdc-0.22/d/phobos/internal/cmain.d --- dmd-1.004/src/phobos/internal/cmain.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/internal/cmain.d 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,6 @@ +private extern (C) int _d_run_main(int argc, char **argv, void * p); +int main(); +extern (C) int main(int argc, char **argv) +{ + return _d_run_main(argc, argv, & main); +} diff -uNrp dmd-1.004/src/phobos/internal/critical.c gdc-0.22/d/phobos/internal/critical.c --- dmd-1.004/src/phobos/internal/critical.c 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/internal/critical.c 2006-12-17 06:03:04.000000000 +0100 @@ -4,6 +4,14 @@ * www.digitalmars.com */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + +#include "config.h" + /* ================================= Win32 ============================ */ #if _WIN32 @@ -75,16 +83,22 @@ void _STD_critical_term() /* ================================= linux ============================ */ -#if linux +#if linux || PHOBOS_USE_PTHREADS + -#include -#include #include +#ifndef HAVE_PTHREAD_MUTEX_RECURSIVE +#define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP +#endif + + /****************************************** * Enter/exit critical section. */ + + /* We don't initialize critical sections unless we actually need them. * So keep a linked list of the ones we do use, and in the static destructor * code, walk the list and release them. @@ -117,7 +131,11 @@ void _d_criticalenter(D_CRITICAL_SECTION { dcs->next = dcs_list; dcs_list = dcs; - pthread_mutex_init(&dcs->cs, &_criticals_attr); +#ifndef PTHREAD_MUTEX_ALREADY_RECURSIVE + pthread_mutex_init(&dcs->cs, & _criticals_attr); +#else + pthread_mutex_init(&dcs->cs, NULL); +#endif } pthread_mutex_unlock(&critical_section.cs); } @@ -126,7 +144,7 @@ void _d_criticalenter(D_CRITICAL_SECTION void _d_criticalexit(D_CRITICAL_SECTION *dcs) { - //printf("_d_criticalexit(dcs = x%x)\n", dcs); + //printf("_d_criticalexit(dcs = x%x)\n", dcs); pthread_mutex_unlock(&dcs->cs); } @@ -134,8 +152,10 @@ void _STI_critical_init() { if (!dcs_list) { //printf("_STI_critical_init()\n"); +#ifndef PTHREAD_MUTEX_ALREADY_RECURSIVE pthread_mutexattr_init(&_criticals_attr); - pthread_mutexattr_settype(&_criticals_attr, PTHREAD_MUTEX_RECURSIVE_NP); + pthread_mutexattr_settype(&_criticals_attr, PTHREAD_MUTEX_RECURSIVE); +#endif // The global critical section doesn't need to be recursive pthread_mutex_init(&critical_section.cs, 0); diff -uNrp dmd-1.004/src/phobos/internal/dgccmain2.d gdc-0.22/d/phobos/internal/dgccmain2.d --- dmd-1.004/src/phobos/internal/dgccmain2.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/internal/dgccmain2.d 2006-12-17 06:03:04.000000000 +0100 @@ -0,0 +1,107 @@ + +/* NOTE: This file is based on dmain2.d from the original DMD distribution. + +*/ + +import object; +import std.c.stdio; +import std.c.stdlib; +import std.c.string; +version (GNU) +{ + private import gcc.config; + private import gc_guess_stack; +} + +extern (C) void _STI_monitor_staticctor(); +extern (C) void _STD_monitor_staticdtor(); +extern (C) void _STI_critical_init(); +extern (C) void _STD_critical_term(); +extern (C) void gc_init(); +extern (C) void gc_term(); +extern (C) void _minit(); +extern (C) void _moduleCtor(); +extern (C) void _moduleDtor(); +extern (C) void _moduleUnitTests(); + +extern (C) bool no_catch_exceptions; + +/*********************************** + * The D main() function supplied by the user's program + */ +//int main(char[][] args); +extern (C) alias int function(char[][] args) main_type; + +/*********************************** + * Substitutes for the C main() function. + * It's purpose is to wrap the call to the D main() + * function and catch any unhandled exceptions. + */ + +/* Note that this is not the C main function, nor does it refer + to the D main function as in the DMD version. The actual C + main is in cmain.d + + This serves two purposes: + 1) Special applications that have a C main declared elsewhere. + + 2) It is possible to create D shared libraries that can be used + by non-D executables. (TODO: Not complete, need a general library + init routine.) +*/ + +extern (C) int _d_run_main(int argc, char **argv, main_type main_func) +{ + char[] *am; + char[][] args; + int i; + int result; + + version (GC_Use_Stack_Guess) + stackOriginGuess = &argv; + version (GNU_CBridge_Stdio) + _d_gnu_cbridge_init_stdio(); + // Win32: original didn't do this -- what about Gcc? + _STI_monitor_staticctor(); + _STI_critical_init(); + gc_init(); + am = cast(char[] *) malloc(argc * (char[]).sizeof); + + void go() + { + _moduleCtor(); + _moduleUnitTests(); + + for (i = 0; i < argc; i++) + { + int len = strlen(argv[i]); + am[i] = argv[i][0 .. len]; + } + + args = am[0 .. argc]; + + result = main_func(args); + _moduleDtor(); + gc_term(); + } + + if (no_catch_exceptions) + go(); + else + { + try + go(); + catch (Object o) + { + printf("Error: "); + o.print(); + exit(EXIT_FAILURE); + } + } + + free(am); + _STD_critical_term(); + _STD_monitor_staticdtor(); + + return result; +} diff -uNrp dmd-1.004/src/phobos/internal/fpmath.d gdc-0.22/d/phobos/internal/fpmath.d --- dmd-1.004/src/phobos/internal/fpmath.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/internal/fpmath.d 2007-01-27 17:44:01.000000000 +0100 @@ -0,0 +1,178 @@ +module gcc.fpmath; + +enum +{ + FP_NAN = 1, + FP_INFINITE, + FP_ZERO, + FP_SUBNORMAL, + FP_NORMAL, +} + +enum RealFormat +{ + SameAsDouble, + DoubleDouble, + Intel80, +} + +struct Info { + static if (real.sizeof == double.sizeof) { + static const RealFormat realFormat = RealFormat.SameAsDouble; + } else version (PPC) { + static const RealFormat realFormat = RealFormat.DoubleDouble; + union real_rec { + real f; + struct { double hd, ld; } + } + } else version (X86) { + static const RealFormat realFormat = RealFormat.Intel80; + union real_rec { + real f; + struct { uint li, mi, hi; } + } + } else version (X86_64) { + static const RealFormat realFormat = RealFormat.Intel80; + union real_rec { + real f; + struct { uint li, mi, hi; } + } + } else { + static assert(0); + } +} + +union float_rec { + float f; + uint i; +} + +int signbit(float f) +{ + float_rec r = void; + r.f = f; + return r.i & 0x80000000; +} + +int fpclassify(float f) +{ + float_rec r = void; + r.f = f; + uint i = r.i & 0x7fffffff; + + if (! i) + return FP_ZERO; + else if (i < 0x00800000) + return FP_SUBNORMAL; + else if (i < 0x7f800000) + return FP_NORMAL; + else if (i < 0x7f800001) + return FP_INFINITE; + else + return FP_NAN; +} + +union double_rec { + double f; + struct { + version (BigEndian) + uint hi, li; + else + uint li, hi; + } +} + +int signbit(double f) +{ + double_rec r = void; + r.f = f; + return r.hi & 0x80000000; +} + +int fpclassify(double f) +{ + double_rec r = void; + r.f = f; + uint i = r.hi & 0x7fffffff; + + if (! (i | r.li)) + return FP_ZERO; + else if (i < 0x00100000) + return FP_SUBNORMAL; + else if (i < 0x7ff00000) + return FP_NORMAL; + else if (i == 0x7ff00000 && ! r.li) + return FP_INFINITE; + else + return FP_NAN; +} + +int signbit(real f) +{ + static if (Info.realFormat == RealFormat.SameAsDouble) { + return signbit(cast(double) f); + } else static if (Info.realFormat == RealFormat.DoubleDouble) { + Info.real_rec r = void; + r.f = f; + return signbit(r.hd); + } else static if (Info.realFormat == RealFormat.Intel80) { + Info.real_rec r = void; + r.f = f; + return r.hi & 0x00008000; + } +} + +int fpclassify(real f) +{ + static if (Info.realFormat == RealFormat.SameAsDouble) { + return fpclassify(cast(double) f); + } else static if (Info.realFormat == RealFormat.DoubleDouble) { + Info.real_rec r = void; + r.f = f; + return fpclassify(r.hd); + } else static if (Info.realFormat == RealFormat.Intel80) { + Info.real_rec r = void; + r.f = f; + uint i = r.hi & 0x00007fff; + uint li = r.li | (r.mi & 0x7fffffff) ; + if (! i && ! li) + return FP_ZERO; + else if (i < 0x00000001 && (r.mi & 0x80000000) == 0) + return FP_SUBNORMAL; + else if (i < 0x00007fff) + return FP_NORMAL; + else if (i == 0x00007fff && ! li) + return FP_INFINITE; + else + return FP_NAN; + } +} + +unittest +{ + static if (Info.realFormat == RealFormat.SameAsDouble) { + const real xrsn = 0x1p-1050; + } else static if (Info.realFormat == RealFormat.DoubleDouble) { + const real xrsn = 0x1p-1050; + } else static if (Info.realFormat == RealFormat.Intel80) { + const real xrsn = 0x1p-16390; + } + + static float[] xfi = [ float.nan, -float.nan, float.infinity, -float.infinity, + 0.0f, -0.0f, 0x1p-135f, -0x1p-135f, 4.2f, -4.2f ]; + static double[] xdi = [ double.nan, -double.nan, double.infinity, -double.infinity, + 0.0, -0.0, 0x1p-1050, -0x1p-1050, 4.2, -4.2 ]; + static real[] xri = [ real.nan, -real.nan, real.infinity, -real.infinity, + 0.0L, -0.0L, xrsn, -xrsn, 4.2L, -4.2L ]; + static int[] xo = [ FP_NAN, FP_NAN, FP_INFINITE, FP_INFINITE, + FP_ZERO, FP_ZERO, FP_SUBNORMAL, FP_SUBNORMAL, FP_NORMAL, FP_NORMAL]; + + foreach (int i, int cls; xo) { + assert( fpclassify(xfi[i]) == xo[i] ); + assert( fpclassify(xdi[i]) == xo[i] ); + assert( fpclassify(xri[i]) == xo[i] ); + assert( ( signbit(xfi[i]) ?1:0 ) == (i & 1) ); + assert( ( signbit(xdi[i]) ?1:0 ) == (i & 1) ); + assert( ( signbit(xri[i]) ?1:0 ) == (i & 1) ); + } +} diff -uNrp dmd-1.004/src/phobos/internal/gc/gcbits.d gdc-0.22/d/phobos/internal/gc/gcbits.d --- dmd-1.004/src/phobos/internal/gc/gcbits.d 2007-01-26 22:58:42.000000000 +0100 +++ gdc-0.22/d/phobos/internal/gc/gcbits.d 2006-06-02 05:31:29.000000000 +0200 @@ -4,13 +4,24 @@ // www.digitalmars.com // Written by Walter Bright +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + import std.c.string; import std.c.stdlib; import std.outofmemory; import std.intrinsic; //version = Asm86; -version = bitops; +version (GNU) { + // bitop intrinsics not implemented yet +} else { + version = bitops; +} + struct GCBits { diff -uNrp dmd-1.004/src/phobos/internal/gc/gc_c.h gdc-0.22/d/phobos/internal/gc/gc_c.h --- dmd-1.004/src/phobos/internal/gc/gc_c.h 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/internal/gc/gc_c.h 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,9 @@ +enum DataSegmentTracking { + ExecutableOnly, + LoadTimeLibrariesOnly, + Dynamic +}; +extern void _D3std2gc8addRangeFPvPvZv(void *, void *); +extern void _D3std2gc11removeRangeFPvZv(void *); +#define GC_add_range(x,y) (_D3std2gc8addRangeFPvPvZv((x),(y))) +#define GC_remove_range(x) (_D3std2gc11removeRangeFPvZv(x)) diff -uNrp dmd-1.004/src/phobos/internal/gc/gc.d gdc-0.22/d/phobos/internal/gc/gc.d --- dmd-1.004/src/phobos/internal/gc/gc.d 2007-01-26 22:58:42.000000000 +0100 +++ gdc-0.22/d/phobos/internal/gc/gc.d 2007-02-03 18:35:36.000000000 +0100 @@ -24,6 +24,12 @@ * distribution. */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, February 2007 +*/ + // Storage allocation @@ -215,38 +221,34 @@ void _d_delclass(Object *p) */ /* For when the array is initialized to 0 */ -ulong _d_newarrayT(TypeInfo ti, size_t length) +Array _d_newarrayT(TypeInfo ti, size_t length) { - void *p; - ulong result; + Array result; auto size = ti.next.tsize(); // array element size debug(PRINTF) printf("_d_newT(length = %d, size = %d)\n", length, size); - if (length == 0 || size == 0) - result = 0; - else + if (length && size) { + result.length = length; size *= length; - p = _gc.malloc(size + 1); - debug(PRINTF) printf(" p = %p\n", p); + result.data = cast(byte*) _gc.malloc(size + 1); if (!(ti.next.flags() & 1)) - _gc.hasNoPointers(p); - memset(p, 0, size); - result = cast(ulong)length + (cast(ulong)cast(uint)p << 32); + _gc.hasNoPointers(result.data); + memset(result.data, 0, size); } return result; } /* For when the array has a non-zero initializer. */ -ulong _d_newarrayiT(TypeInfo ti, size_t length) +Array _d_newarrayiT(TypeInfo ti, size_t length) { - ulong result; + Array result; auto size = ti.next.tsize(); // array element size //debug(PRINTF) printf("_d_newarrayiT(length = %d, size = %d, isize = %d)\n", length, size, isize); if (length == 0 || size == 0) - result = 0; + { } else { auto initializer = ti.next.init(); @@ -275,23 +277,22 @@ ulong _d_newarrayiT(TypeInfo ti, size_t memcpy(p + u, q, isize); } } - va_end(q); - result = cast(ulong)length + (cast(ulong)cast(uint)p << 32); + result.length = length; + result.data = cast(byte*) p ; } return result; } -ulong _d_newarraymT(TypeInfo ti, int ndims, ...) +void[] _d_newarraymTp(TypeInfo ti, int ndims, size_t* pdim) { - ulong result; + void[] result = void; //debug(PRINTF) //printf("_d_newarraymT(ndims = %d)\n", ndims); if (ndims == 0) - result = 0; + result = null; else - { va_list q; - va_start!(int)(q, ndims); + { void[] foo(TypeInfo ti, size_t* pdim, int ndims) { @@ -315,34 +316,30 @@ ulong _d_newarraymT(TypeInfo ti, int ndi return p; } - size_t* pdim = cast(size_t *)q; - result = cast(ulong)foo(ti, pdim, ndims); + result = foo(ti, pdim, ndims); //printf("result = %llx\n", result); version (none) { for (int i = 0; i < ndims; i++) { - printf("index %d: %d\n", i, va_arg!(int)(q)); + printf("index %d: %d\n", i, pdim[i]); } } - va_end(q); } return result; } -ulong _d_newarraymiT(TypeInfo ti, int ndims, ...) +void[] _d_newarraymiTp(TypeInfo ti, int ndims, size_t* pdim) { - ulong result; + void[] result = void; //debug(PRINTF) //printf("_d_newarraymi(size = %d, ndims = %d)\n", size, ndims); if (ndims == 0) - result = 0; + result = null; else { - va_list q; - va_start!(int)(q, ndims); void[] foo(TypeInfo ti, size_t* pdim, int ndims) { @@ -365,19 +362,17 @@ ulong _d_newarraymiT(TypeInfo ti, int nd return p; } - size_t* pdim = cast(size_t *)q; - result = cast(ulong)foo(ti, pdim, ndims); + result = foo(ti, pdim, ndims); //printf("result = %llx\n", result); version (none) { for (int i = 0; i < ndims; i++) { - printf("index %d: %d\n", i, va_arg!(int)(q)); - printf("init = %d\n", va_arg!(int)(q)); + printf("index %d: %d\n", i, pdim[i]); + printf("init = %d\n", *cast(int*)pinit); } } - va_end(q); } return result; } @@ -483,6 +478,14 @@ body if (newlength) { + version (GNU) + { + // required to output the label; + static char x = 0; + if (x) + goto Loverflow; + } + version (D_InlineAsm_X86) { size_t newsize = void; @@ -577,6 +580,14 @@ body if (newlength) { + version (GNU) + { + // required to output the label; + static char x = 0; + if (x) + goto Loverflow; + } + version (D_InlineAsm_X86) { size_t newsize = void; @@ -657,7 +668,7 @@ Loverflow: */ extern (C) -long _d_arrayappendT(TypeInfo ti, Array *px, byte[] y) +Array _d_arrayappendT(TypeInfo ti, Array *px, byte[] y) { auto size = ti.next.tsize(); // array element size size_t cap = _gc.capacity(px.data); @@ -674,7 +685,7 @@ long _d_arrayappendT(TypeInfo ti, Array } px.length = newlength; memcpy(px.data + length * size, y.ptr, y.length * size); - return *cast(long*)px; + return *px; } size_t newCapacity(size_t newlength, size_t size) @@ -745,7 +756,7 @@ size_t newCapacity(size_t newlength, siz } extern (C) -byte[] _d_arrayappendcT(TypeInfo ti, inout byte[] x, ...) +byte[] _d_arrayappendcTp(TypeInfo ti, inout byte[] x, void *argp) { auto size = ti.next.tsize(); // array element size size_t cap = _gc.capacity(x.ptr); @@ -768,10 +779,9 @@ byte[] _d_arrayappendcT(TypeInfo ti, ino memcpy(newdata, x.ptr, length * size); (cast(void **)(&x))[1] = newdata; } - byte *argp = cast(byte *)(&ti + 2); *cast(size_t *)&x = newlength; - (cast(byte *)x)[length * size .. newlength * size] = argp[0 .. size]; + (cast(byte *)x)[length * size .. newlength * size] = (cast(byte*)argp)[0 .. size]; assert((cast(size_t)x.ptr & 15) == 0); assert(_gc.capacity(x.ptr) > x.length * size); return x; @@ -836,13 +846,14 @@ byte[] _d_arraycatnT(TypeInfo ti, uint n byte[]* p; uint i; byte[] b; + va_list va; auto size = ti.next.tsize(); // array element size - p = cast(byte[]*)(&n + 1); + va_start!(typeof(n))(va, n); for (i = 0; i < n; i++) { - b = *p++; + b = va_arg!(typeof(b))(va); length += b.length; } if (!length) @@ -851,12 +862,12 @@ byte[] _d_arraycatnT(TypeInfo ti, uint n a = new byte[length * size]; if (!(ti.next.flags() & 1)) _gc.hasNoPointers(a.ptr); - p = cast(byte[]*)(&n + 1); + va_start!(typeof(n))(va, n); uint j = 0; for (i = 0; i < n; i++) { - b = *p++; + b = va_arg!(typeof(b))(va); if (b.length) { memcpy(&a[j], b.ptr, b.length * size); @@ -869,6 +880,7 @@ byte[] _d_arraycatnT(TypeInfo ti, uint n return a; } +version (GNU) { } else extern (C) void* _d_arrayliteralT(TypeInfo ti, size_t length, ...) { @@ -919,7 +931,7 @@ struct Array2 } extern (C) -long _adDupT(TypeInfo ti, Array2 a) +Array2 _adDupT(TypeInfo ti, Array2 a) out (result) { auto szelem = ti.next.tsize(); // array element size @@ -939,7 +951,7 @@ long _adDupT(TypeInfo ti, Array2 a) r.length = a.length; memcpy(r.ptr, a.ptr, size); } - return *cast(long*)(&r); + return r; } unittest diff -uNrp dmd-1.004/src/phobos/internal/gc/gc_dyld.c gdc-0.22/d/phobos/internal/gc/gc_dyld.c --- dmd-1.004/src/phobos/internal/gc/gc_dyld.c 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/internal/gc/gc_dyld.c 2006-06-06 00:12:02.000000000 +0200 @@ -0,0 +1,80 @@ +// Could config test HAVE_PRIVATE_EXTERN, but this should be okay +#ifndef __private_extern__ +#define __private_extern__ extern +#include +#undef __private_extern__ +#else +#include +#endif + +#include +#include + +#include "gc_c.h" + +const static struct { + const char *seg; + const char *sect; +} GC_dyld_sections[] = { + { SEG_DATA, SECT_DATA }, + { SEG_DATA, SECT_BSS }, + { SEG_DATA, SECT_COMMON } +}; + + +/* This should never be called by a thread holding the lock */ +static void +on_dyld_add_image(const struct mach_header* hdr, intptr_t slide) { + unsigned i; + unsigned long start, end; + const struct section *sec; + + for (i = 0; + i < sizeof(GC_dyld_sections) / sizeof(GC_dyld_sections[0]); + i++) { + + sec = getsectbynamefromheader(hdr, GC_dyld_sections[i].seg, + GC_dyld_sections[i].sect); + if (sec == NULL || sec->size == 0) + continue; + start = slide + sec->addr; + end = start + sec->size; + + GC_add_range((void*) start, (void*) end); + } +} + +/* This should never be called by a thread holding the lock */ +static void +on_dyld_remove_image(const struct mach_header* hdr, intptr_t slide) { + unsigned i; + unsigned long start, end; + const struct section *sec; + + for(i = 0; + i < sizeof(GC_dyld_sections) / sizeof(GC_dyld_sections[0]); + i++) { + + sec = getsectbynamefromheader(hdr, + GC_dyld_sections[i].seg, GC_dyld_sections[i].sect); + if (sec == NULL || sec->size == 0) + continue; + start = slide + sec->addr; + end = start + sec->size; + + GC_remove_range((void*) start);//, (void*) end); + } +} + +void _d_gcc_dyld_start(enum DataSegmentTracking mode) +{ + static int started = 0; + + if (! started) { + started = 1; + _dyld_register_func_for_add_image(on_dyld_add_image); + _dyld_register_func_for_remove_image(on_dyld_remove_image); + } + + // (for LoadTimeLibrariesOnly:) Can't unregister callbacks +} diff -uNrp dmd-1.004/src/phobos/internal/gc/gc_freebsd.c gdc-0.22/d/phobos/internal/gc/gc_freebsd.c --- dmd-1.004/src/phobos/internal/gc/gc_freebsd.c 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/internal/gc/gc_freebsd.c 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,12 @@ +#include +#include +#include + +int _d_gcc_gc_freebsd_stack(void ** out_origin) +{ + int nm[2] = {CTL_KERN, KERN_USRSTACK}; + size_t len = sizeof(void *); + int r = sysctl(nm, 2, out_origin, &len, NULL, 0); + + return ! r; +} diff -uNrp dmd-1.004/src/phobos/internal/gc/gcgcc.d gdc-0.22/d/phobos/internal/gc/gcgcc.d --- dmd-1.004/src/phobos/internal/gc/gcgcc.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/internal/gc/gcgcc.d 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,286 @@ +private import gcgccextern; +private import std.gc; +private import std.c.stdlib; +private import std.string; // for memmove + +debug(ProcMaps) + private import std.c.stdio; + +/* ------- Memory allocation ------------- */ + +version (GC_Use_Alloc_MMap) +{ + private import std.c.unix.unix; + + void *os_mem_map(uint nbytes) + { void *p; + p = mmap(null, nbytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + return (p == MAP_FAILED) ? null : p; + } + int os_mem_commit(void *base, uint offset, uint nbytes) + { + return 0; + } + + int os_mem_decommit(void *base, uint offset, uint nbytes) + { + return 0; + } + + int os_mem_unmap(void *base, uint nbytes) + { + return munmap(base, nbytes); + } +} +else version (GC_Use_Alloc_Valloc) +{ + extern (C) void * valloc(size_t); + void *os_mem_map(uint nbytes) { return valloc(nbytes); } + int os_mem_commit(void *base, uint offset, uint nbytes) { return 0; } + int os_mem_decommit(void *base, uint offset, uint nbytes) { return 0; } + int os_mem_unmap(void *base, uint nbytes) { free(base); return 0; } +} +else version (GC_Use_Alloc_Malloc) +{ + /* Assumes malloc granularity is at least (void *).sizeof. If + (req_size + PAGESIZE) is allocated, and the pointer is rounded + up to PAGESIZE alignment, there will be space for a void* at the + end after PAGESIZE bytes used by the GC. */ + + private import gcx; // for PAGESIZE + + const uint PAGE_MASK = PAGESIZE - 1; + + void *os_mem_map(uint nbytes) + { byte * p, q; + p = cast(byte *) malloc(nbytes + PAGESIZE); + q = p + ((PAGESIZE - ((cast(size_t) p & PAGE_MASK))) & PAGE_MASK); + * cast(void**)(q + nbytes) = p; + return q; + } + int os_mem_commit(void *base, uint offset, uint nbytes) + { + return 0; + } + + int os_mem_decommit(void *base, uint offset, uint nbytes) + { + return 0; + } + + int os_mem_unmap(void *base, uint nbytes) + { + free( * cast(void**)( cast(byte*) base + nbytes ) ); + return 0; + } +} +else version (GC_Use_Alloc_Fixed_Heap) +{ + // TODO + static assert(0); +} +else +{ + static assert(0); +} + + +/* ------- Stack origin ------------- */ + +version (GC_Use_Stack_Guess) + private import gc_guess_stack; + +version (GC_Use_Stack_FreeBSD) + extern (C) int _d_gcc_gc_freebsd_stack(void **); + +void *os_query_stackBottom() +{ + version (GC_Use_Stack_GLibC) + { + return __libc_stack_end; + } + else version (GC_Use_Stack_Guess) + { + // dmainwhatever should be private too + // import main? + return stackOriginGuess; + } + else version (GC_Use_Stack_FreeBSD) + { + void * stack_origin; + if (_d_gcc_gc_freebsd_stack(& stack_origin)) + return stack_origin; + else + // No way to signal an error + return null; + } + else version (GC_Use_Stack_Scan) + { + static assert(0); + } + else version (GC_Use_Stack_Fixed) + { + version (darwin) + return cast(void*) 0xc0000000; + else + static assert(0); + } + else + { + static assert(0); + } +} + +// std.thread needs to know the stack origin +extern (C) void* _d_gcc_query_stack_origin() +{ + return os_query_stackBottom(); +} + + +/* ------- Data segments ------------- */ + +version (GC_Use_Data_Dyld) + extern (C) void _d_gcc_dyld_start(DataSegmentTracking mode); + +version (GC_Use_Data_Proc_Maps) +{ + private import std.c.unix.unix; + private import std.c.stdlib; +} + + +/* + It is assumed that this is called during GC initialization and + only once. +*/ + +void os_query_staticdataseg(void **base, uint *nbytes) +{ + // Can't assume the input addresses are word-aligned + static void * adjust_up(void * p) + { + const int S = (void *).sizeof; + return p + ((S - (cast(uint)p & (S-1))) & (S-1)); // cast ok even if 64-bit + } + static void * adjust_down(void * p) + { + const int S = (void *).sizeof; + return p - (cast(uint) p & (S-1)); + } + + void * main_data_start; + void * main_data_end; + + *base = null; + *nbytes = 0; + + version (GC_Use_Data_Dyld) + { + _d_gcc_dyld_start(DataSegmentTracking.Dynamic); + return; // no need for any other method + } + + version (GC_Use_Data_Fixed) + { + static if (FM.One) { + main_data_start = adjust_up ( & Data_Start ); + main_data_end = adjust_down( & Data_End ); + *base = main_data_start; + *nbytes = main_data_end - main_data_start; + } else static if (FM.Two) { + main_data_start = adjust_up ( & Data_Start ); + main_data_end = adjust_down( & Data_End ); + *base = main_data_start; + *nbytes = main_data_end - main_data_start; + addRange(adjust_up( & Data_Start_2 ), adjust_down( & Data_End_2 )); + } else static if (FM.MinMax) { + static void * min(void *a, void *b) { return a < b ? a : b; } + static void * max(void *a, void *b) { return a > b ? a : b; } + main_data_start = adjust_up ( & Data_Start < & Data_Start_2 ? & Data_Start : & Data_Start_2 ); + main_data_end = adjust_down( & Data_End > & Data_End_2 ? & Data_End : & Data_End_2 ); + *base = main_data_start; + *nbytes = main_data_end - main_data_start; + } + //goto have_main_data; + } + + //have_main_data: + + version (GC_Use_Data_Proc_Maps) + { + // TODO: Exclude zero-mapped regions... + + int fd = open("/proc/self/maps", O_RDONLY); + int count; // %% need to configure ret for read.. + char buf[2024]; + char * p; + char * e; + char * s; + void * start; + void * end; + + p = buf; + if (fd != -1) { + while ( (count = read(fd, p, buf.sizeof - (p - buf.ptr))) > 0 ) { + e = p + count; + p = buf; + while (1) { + s = p; + while (p < e && *p != '\n') + p++; + if (p < e) { + // parse the entry in [s, p) + version (GNU_BitsPerPointer32) { + enum Ofs { + Write_Prot = 19, + Start_Addr = 0, + End_Addr = 9, + Addr_Len = 8, + } + } else version (GNU_BitsPerPointer64) { + enum Ofs { + Write_Prot = 35, + Start_Addr = 0, + End_Addr = 9, + Addr_Len = 17, + } + } else { + static assert(0); + } + + // %% this is wrong for 64-bit: + // uint strtoul(char *,char **,int); + + if (s[Ofs.Write_Prot] == 'w') { + s[Ofs.Start_Addr + Ofs.Addr_Len] = '\0'; + s[Ofs.End_Addr + Ofs.Addr_Len] = '\0'; + start = cast(void *) strtoul(s + Ofs.Start_Addr, null, 16); + end = cast(void *) strtoul(s + Ofs.End_Addr, null, 16); + + // 1. Exclude anything overlapping [main_data_start,main_data_end) + // 2. Exclude stack + if ( (! main_data_end || + ! (main_data_start >= start && main_data_end <= end)) && + ! (& buf >= start && & buf < end)) { + // we already have static data from this region. anything else + // is heap (%% check) + debug (ProcMaps) + printf("Adding map range %p 0%p\n", start, end); + addRange(start, end); + } + } + + p++; + } else { + count = p - s; + memmove(buf, s, count); + p = buf.ptr + count; + break; + } + } + } + close(fd); + } + } +} diff -uNrp dmd-1.004/src/phobos/internal/gc/gcgccextern.d gdc-0.22/d/phobos/internal/gc/gcgccextern.d --- dmd-1.004/src/phobos/internal/gc/gcgccextern.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/internal/gc/gcgccextern.d 2006-06-11 20:57:00.000000000 +0200 @@ -0,0 +1,68 @@ +module gcc.gccextern; + +version(GC_Use_Stack_GLibC) + extern (C) void * __libc_stack_end; + +version(GC_Use_Data_Fixed) +{ + extern (C) int _data; + extern (C) int __data_start; + extern (C) int _end; + extern (C) int _data_start__; + extern (C) int _data_end__; + extern (C) int _bss_start__; + extern (C) int _bss_end__; + extern (C) int __fini_array_end; + + /* %% Move all this to configure script to test if it actually works? + --enable-gc-data-fixed=Mode,s1,e1,s2,e2 + .. the Mode can be a version instead of enum trick + */ + + version (aix) + { + alias _data Data_Start; + alias _end Data_End; + enum FM { One = 1, MinMax = 0, Two = 0 } + } + else version (cygwin) + { + alias _data_start__ Data_Start; + alias _data_end__ Data_End; + alias _bss_start__ Data_Start_2; + alias _bss_end__ Data_End_2; + enum FM { MinMax = 1, One = 0, Two = 0 } + } + else version (freebsd) + { + // use '_etext' if '__fini_array_end' doesn't work + /* There is a bunch of read-only data after .data and before .bss, but + no linker symbols to find it. Would have to set up a fault handler + and scan... */ + alias __fini_array_end Data_Start; + alias _end Data_End; + enum FM { One = 1, MinMax = 0, Two = 0 } + } + else version (linux) + { + alias __data_start Data_Start; + alias _end Data_End; + /* possible better way: + [__data_start,_DYNAMIC) and [_edata/edata or __bss_start,_end/end) + This doesn't really save much.. a better linker script is needed. + */ + enum FM { One = 1, MinMax = 0, Two = 0 } + } + else version (skyos) + { + alias _data_start__ Data_Start; + alias _bss_end__ Data_End; + enum FM { One = 1, MinMax = 0, Two = 0 } + } +} + +enum DataSegmentTracking { + ExecutableOnly, + LoadTimeLibrariesOnly, + Dynamic +} diff -uNrp dmd-1.004/src/phobos/internal/gc/gc_guess_stack.d gdc-0.22/d/phobos/internal/gc/gc_guess_stack.d --- dmd-1.004/src/phobos/internal/gc/gc_guess_stack.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/internal/gc/gc_guess_stack.d 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,3 @@ +module gcc.gc_guess_stack; +void * stackOriginGuess; + diff -uNrp dmd-1.004/src/phobos/internal/gc/gcold.d gdc-0.22/d/phobos/internal/gc/gcold.d --- dmd-1.004/src/phobos/internal/gc/gcold.d 2007-01-26 22:58:42.000000000 +0100 +++ gdc-0.22/d/phobos/internal/gc/gcold.d 2007-02-03 18:35:36.000000000 +0100 @@ -36,44 +36,39 @@ module std.gcold; import gc; extern (C) -ulong _d_newarrayi(size_t length, size_t size, ...) +Array _d_newarrayip(size_t length, size_t size, void * init) { - void *p; - ulong result; + Array result; - //debug(PRINTF) printf("_d_newarrayi(length = %d, size = %d)\n", length, size); - if (length == 0 || size == 0) - result = 0; - else + if (length && size) { - //void* q = cast(void*)(&size + 1); // pointer to initializer - va_list q; - va_start!(size_t)(q, size); // q is pointer to ... initializer - p = _gc.malloc(length * size + 1); - debug(PRINTF) printf(" p = %p\n", p); + result.length = length; + result.data = cast(byte*) _gc.malloc(length * size + 1); if (size == 1) - memset(p, *cast(ubyte*)q, length); + memset(result.data, * cast(ubyte*) init, length); else if (size == int.sizeof) { - int init = *cast(int*)q; + int init_val = *cast(int*)init; + void * p = result.data; for (uint u = 0; u < length; u++) { - (cast(int*)p)[u] = init; + (cast(int*)p)[u] = init_val; } } else { + void * p = result.data; for (uint u = 0; u < length; u++) { - memcpy(p + u * size, q, size); + memcpy(p, init, size); + p += size; } } - va_end(q); - result = cast(ulong)length + (cast(ulong)cast(uint)p << 32); } return result; } +version (GNU) { } else extern (C) ulong _d_newarrayii(size_t length, size_t size, size_t isize ...) { @@ -115,17 +110,16 @@ ulong _d_newarrayii(size_t length, size_ } extern (C) -ulong _d_newm(size_t size, int ndims, ...) +void[] _d_newmp(size_t size, int ndims, size_t* pdim) { - ulong result; + void[] result = void; //debug(PRINTF) //printf("_d_newm(size = %d, ndims = %d)\n", size, ndims); if (size == 0 || ndims == 0) - result = 0; + result = null; else - { va_list q; - va_start!(int)(q, ndims); + { void[] foo(size_t* pdim, int ndims) { @@ -147,35 +141,31 @@ ulong _d_newm(size_t size, int ndims, .. return p; } - size_t* pdim = cast(size_t *)q; - result = cast(ulong)foo(pdim, ndims); + result = foo(pdim, ndims); //printf("result = %llx\n", result); version (none) { for (int i = 0; i < ndims; i++) { - printf("index %d: %d\n", i, va_arg!(int)(q)); + printf("index %d: %d\n", i, pdim[i]); } } - va_end(q); } return result; } extern (C) -ulong _d_newarraymi(size_t size, int ndims, ...) +void[] _d_newarraymip(size_t size, int ndims, size_t* pdim, size_t mult, void* pinit) { - ulong result; + void[] result = void; //debug(PRINTF) //printf("_d_newarraymi(size = %d, ndims = %d)\n", size, ndims); if (size == 0 || ndims == 0) - result = 0; + result = null; else - { void* pinit; // pointer to initializer - va_list q; - va_start!(int)(q, ndims); + { void[] foo(size_t* pdim, int ndims) { @@ -183,12 +173,13 @@ ulong _d_newarraymi(size_t size, int ndi void[] p; if (ndims == 1) - { p = _gc.malloc(dim * size + 1)[0 .. dim]; + { p = _gc.malloc(dim * mult * size + 1)[0 .. dim]; if (size == 1) memset(p.ptr, *cast(ubyte*)pinit, dim); else { - for (size_t u = 0; u < dim; u++) + size_t n = dim * mult; + for (size_t u = 0; u < n; u++) { memcpy(p.ptr + u * size, pinit, size); } @@ -205,20 +196,17 @@ ulong _d_newarraymi(size_t size, int ndi return p; } - size_t* pdim = cast(size_t *)q; - pinit = pdim + ndims; - result = cast(ulong)foo(pdim, ndims); + result = foo(pdim, ndims); //printf("result = %llx\n", result); version (none) { for (int i = 0; i < ndims; i++) { - printf("index %d: %d\n", i, va_arg!(int)(q)); - printf("init = %d\n", va_arg!(int)(q)); + printf("index %d: %d\n", i, pdim[i]); + printf("init = %d\n", *cast(int*)pinit); } } - va_end(q); } return result; } @@ -229,20 +217,25 @@ ulong _d_newarraymi(size_t size, int ndi */ extern (C) -ulong _d_new(size_t length, size_t size) +Array _d_new(size_t length, size_t size) { void *p; - ulong result; + Array result; debug(PRINTF) printf("_d_new(length = %d, size = %d)\n", length, size); + /* if (length == 0 || size == 0) result = 0; else + */ + if (length && size) { p = _gc.malloc(length * size + 1); debug(PRINTF) printf(" p = %p\n", p); memset(p, 0, length * size); - result = cast(ulong)length + (cast(ulong)cast(uint)p << 32); + result.length = length; + result.data = cast(byte*)p; + return result; } return result; } @@ -267,6 +260,14 @@ body if (newlength) { + version (GNU) + { + // required to output the label; + static char x = 0; + if (x) + goto Loverflow; + } + version (D_InlineAsm_X86) { size_t newsize = void; @@ -327,7 +328,7 @@ Loverflow: * (obsolete, replaced by _d_arraysetlength3) */ extern (C) -byte[] _d_arraysetlength2(size_t newlength, size_t sizeelem, Array *p, ...) +byte[] _d_arraysetlength2p(size_t newlength, size_t sizeelem, Array *p, void * init) in { assert(sizeelem); @@ -346,6 +347,14 @@ body if (newlength) { + version (GNU) + { + // required to output the label; + static char x = 0; + if (x) + goto Loverflow; + } + version (D_InlineAsm_X86) { size_t newsize = void; @@ -387,21 +396,18 @@ body newdata = cast(byte *)_gc.malloc(newsize + 1); } - va_list q; - va_start!(Array *)(q, p); // q is pointer to initializer - if (newsize > size) { if (sizeelem == 1) { //printf("newdata = %p, size = %d, newsize = %d, *q = %d\n", newdata, size, newsize, *cast(byte*)q); - newdata[size .. newsize] = *(cast(byte*)q); + newdata[size .. newsize] = *(cast(byte*)init); } else { for (size_t u = size; u < newsize; u += sizeelem) { - memcpy(newdata + u, q, sizeelem); + memcpy(newdata + u, init, sizeelem); } } } @@ -554,8 +560,8 @@ bit[] _d_arrayappendcb(inout bit[] x, bi * ... initializer */ extern (C) -byte[] _d_arraysetlength3(size_t newlength, size_t sizeelem, Array *p, - size_t initsize, ...) +byte[] _d_arraysetlength3p(size_t newlength, size_t sizeelem, Array *p, + size_t initsize, void *init) in { assert(sizeelem); @@ -577,6 +583,14 @@ body if (newlength) { + version (GNU) + { + // required to output the label; + static char x = 0; + if (x) + goto Loverflow; + } + version (D_InlineAsm_X86) { size_t newsize = void; @@ -618,21 +632,18 @@ body newdata = cast(byte *)_gc.malloc(newsize + 1); } - va_list q; - va_start!(size_t)(q, initsize); // q is pointer to initializer - if (newsize > size) { if (initsize == 1) { //printf("newdata = %p, size = %d, newsize = %d, *q = %d\n", newdata, size, newsize, *cast(byte*)q); - newdata[size .. newsize] = *(cast(byte*)q); + newdata[size .. newsize] = *(cast(byte*)init); } else { for (size_t u = size; u < newsize; u += initsize) { - memcpy(newdata + u, q, initsize); + memcpy(newdata + u, init, initsize); } } } @@ -652,7 +663,7 @@ Loverflow: extern (C) -long _d_arrayappend(Array *px, byte[] y, size_t size) +Array _d_arrayappend(Array *px, byte[] y, size_t size) { size_t cap = _gc.capacity(px.data); @@ -667,12 +678,12 @@ long _d_arrayappend(Array *px, byte[] y, } px.length = newlength; memcpy(px.data + length * size, y.ptr, y.length * size); - return *cast(long*)px; + return *px; } extern (C) -byte[] _d_arrayappendc(inout byte[] x, in size_t size, ...) +byte[] _d_arrayappendcp(inout byte[] x, in size_t size, void *argp) { size_t cap = _gc.capacity(x.ptr); size_t length = x.length; @@ -692,10 +703,9 @@ byte[] _d_arrayappendc(inout byte[] x, i memcpy(newdata, x.ptr, length * size); (cast(void **)(&x))[1] = newdata; } - byte *argp = cast(byte *)(&size + 1); *cast(size_t *)&x = newlength; - (cast(byte *)x)[length * size .. newlength * size] = argp[0 .. size]; + (cast(byte *)x)[length * size .. newlength * size] = (cast(byte*)argp)[0 .. size]; assert((cast(size_t)x.ptr & 15) == 0); assert(_gc.capacity(x.ptr) > x.length * size); return x; @@ -752,27 +762,27 @@ extern (C) byte[] _d_arraycatn(uint size, uint n, ...) { byte[] a; uint length; - byte[]* p; uint i; byte[] b; + va_list va; - p = cast(byte[]*)(&n + 1); + va_start!(typeof(n))(va, n); for (i = 0; i < n; i++) { - b = *p++; + b = va_arg!(typeof(b))(va); length += b.length; } if (!length) return null; a = new byte[length * size]; - p = cast(byte[]*)(&n + 1); + va_start!(typeof(n))(va, n); uint j = 0; for (i = 0; i < n; i++) { - b = *p++; + b = va_arg!(typeof(b))(va); if (b.length) { memcpy(&a[j], b.ptr, b.length * size); @@ -886,6 +896,8 @@ bit[] _d_arraysetbit2(bit[] ba, bit valu } } +version (GNU) { /* _d_arrayliteral not used; can't always be compiled */ } +else extern (C) void* _d_arrayliteral(size_t size, size_t length, ...) { @@ -926,20 +938,20 @@ void* _d_arrayliteral(size_t size, size_ * Support for array.dup property. */ -extern (C) long _adDup(Array2 a, int szelem) +extern (C) Array _adDup(Array a, int szelem) out (result) { - assert(memcmp((*cast(Array2*)&result).ptr, a.ptr, a.length * szelem) == 0); + assert(memcmp(result.ptr, a.ptr, a.length * szelem) == 0); } body { - Array2 r; + Array r; auto size = a.length * szelem; r.ptr = cast(void *) new byte[size]; r.length = a.length; memcpy(r.ptr, a.ptr, size); - return *cast(long*)(&r); + return r; } unittest @@ -964,10 +976,10 @@ unittest version (none) { -extern (C) long _adDupBit(Array a) +extern (C) Array _adDupBit(Array a) out (result) { - assert(memcmp((*cast(Array*)(&result)).ptr, a.ptr, (a.length + 7) / 8) == 0); + assert(memcmp(result.ptr, a.ptr, (a.length + 7) / 8) == 0); } body { @@ -977,7 +989,7 @@ extern (C) long _adDupBit(Array a) r.ptr = cast(void *) new uint[size]; r.length = a.length; memcpy(r.ptr, a.ptr, size * uint.sizeof); - return *cast(long*)(&r); + return r; } unittest diff -uNrp dmd-1.004/src/phobos/internal/gc/gcx.d gdc-0.22/d/phobos/internal/gc/gcx.d --- dmd-1.004/src/phobos/internal/gc/gcx.d 2007-01-26 22:58:42.000000000 +0100 +++ gdc-0.22/d/phobos/internal/gc/gcx.d 2007-02-03 17:34:12.000000000 +0100 @@ -1,10 +1,16 @@ // -// Copyright (C) 2001-2007 by Digital Mars +// Copyright (C) 2001-2006 by Digital Mars // All Rights Reserved // Written by Walter Bright // www.digitalmars.com -// D Programming Language Garbage Collector implementation +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, July 2006 +*/ + +// D Garbage Collector implementation /************** Debugging ***************************/ @@ -37,17 +43,29 @@ import std.outofmemory; import std.gc; import gcstats; +version (GNU) +{ + private import gcc.builtins; +} + version (Win32) { import win32; import std.c.windows.windows; } - -version (linux) +else version (GNU) +{ + private import gcgcc; +} +else version (linux) { import gclinux; } +/*version (BigEndian) + private import std.intrinsic;*/ + + version (MULTI_THREADED) { @@ -57,6 +75,8 @@ version (MULTI_THREADED) //alias GC* gc_t; alias GC gc_t; +version (X86) version (D_InlineAsm) { version = Asm86; } + /* ======================= Leak Detector =========================== */ debug (LOGGING) @@ -183,7 +203,11 @@ class GC { setStackBottom(win32.os_query_stackBottom()); } - version (linux) + else version (GNU) + { + setStackBottom(gcgcc.os_query_stackBottom()); + } + else version (linux) { setStackBottom(gclinux.os_query_stackBottom()); } @@ -291,9 +315,11 @@ class GC // Return next item from free list gcx.bucket[bin] = (cast(List *)p).next; - //memset(p + size, 0, binsize[bin] - size); - // 'inline' memset - Dave Fladebo. - foreach(inout byte b; cast(byte[])(p + size)[0..binsize[bin] - size]) { b = 0; } + version(GNU) + memset(p + size, 0, binsize[bin] - size); + else + // 'inline' memset - Dave Fladebo. + foreach(inout byte b; cast(byte[])(p + size)[0..binsize[bin] - size]) { b = 0; } //debug(PRINTF) printf("\tmalloc => %x\n", p); debug (MEMSTOMP) memset(p, 0xF0, size); } @@ -559,7 +585,13 @@ class GC //debug(PRINTF) printf("+GC.scanStaticData()\n"); os_query_staticdataseg(&pbot, &nbytes); ptop = pbot + nbytes; - g.addRange(pbot, ptop); + version (GNU) { + if (pbot) { + g.addRange(pbot, ptop); + } + } else { + g.addRange(pbot, ptop); + } //debug(PRINTF) printf("-GC.scanStaticData()\n"); } @@ -569,7 +601,13 @@ class GC uint nbytes; os_query_staticdataseg(&pbot, &nbytes); - g.removeRange(pbot); + version (GNU) { + if (pbot) { + g.removeRange(pbot); + } + } else { + g.removeRange(pbot); + } } @@ -979,7 +1017,7 @@ struct Gcx void addRange(void *pbot, void *ptop) { - debug(PRINTF) printf("Thread %x ", pthread_self()); + debug(THREADINVARIANT) { debug(PRINTF) printf("Thread %x ", pthread_self()); } debug(PRINTF) printf("%x.Gcx::addRange(%x, %x), nranges = %d\n", this, pbot, ptop, nranges); if (nranges == rangedim) { @@ -1003,7 +1041,7 @@ struct Gcx void removeRange(void *pbot) { - debug(PRINTF) printf("Thread %x ", pthread_self()); + debug(THREADINVARIANT) { debug(PRINTF) printf("Thread %x ", pthread_self()); } debug(PRINTF) printf("%x.Gcx.removeRange(%x), nranges = %d\n", this, pbot, nranges); for (uint i = nranges; i--;) { @@ -1407,15 +1445,30 @@ struct Gcx // get put on the stack so they'll be scanned void *sp; uint result; - asm + version (GNU) { - pushad ; - mov sp[EBP],ESP ; + __builtin_unwind_init(); + sp = & sp; + } + else + { + asm + { + pushad ; + mov sp[EBP],ESP ; + } } result = fullcollect(sp); - asm + version (GNU) { - popad ; + // nothing to do + } + else + { + asm + { + popad ; + } } return result; } @@ -1484,7 +1537,18 @@ struct Gcx mark(cast(void *)context.Esp, t.stackBottom); mark(&context.Edi, &context.Eip); } - version (linux) + else version (GNU) + { + if (t.isSelf()) + t.stackTop = Thread.getESP(); + + //%%fry printf("top=%08x bot=%08x ext=%08x\n", t.stackTop, t.stackBottom, Thread.getESP());//%%try + version (STACKGROWSDOWN) + mark(t.stackTop, t.stackBottom); + else + mark(t.stackBottom, t.stackTop); + } + else version (linux) { // The registers are already stored in the stack //printf("Thread: ESP = x%x, stackBottom = x%x, isSelf = %d\n", Thread.getESP(), t.stackBottom, t.isSelf()); @@ -1555,6 +1619,9 @@ struct Gcx *b = 0; o = pool.baseAddr + (b - bbase) * 32 * 16; + /* version (BigEndian) + bitm = bswap(bitm); + */ if (!(bitm & 0xFFFF)) { bitm >>= 16; @@ -1828,7 +1895,7 @@ struct Gcx Log log; log.p = p; - log.sizeof = size; + log.size = size; log.line = GC.line; log.file = GC.file; log.parent = null; diff -uNrp dmd-1.004/src/phobos/internal/gc/testgc.d gdc-0.22/d/phobos/internal/gc/testgc.d --- dmd-1.004/src/phobos/internal/gc/testgc.d 2007-01-26 22:58:42.000000000 +0100 +++ gdc-0.22/d/phobos/internal/gc/testgc.d 2006-12-17 06:03:04.000000000 +0100 @@ -4,6 +4,12 @@ // Written by Walter Bright // www.digitalmars.com +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, July 2006 +*/ + // GC tester program import std.c.stdio; diff -uNrp dmd-1.004/src/phobos/internal/gc/win32.d gdc-0.22/d/phobos/internal/gc/win32.d --- dmd-1.004/src/phobos/internal/gc/win32.d 2007-01-26 22:58:42.000000000 +0100 +++ gdc-0.22/d/phobos/internal/gc/win32.d 2007-01-27 17:44:01.000000000 +0100 @@ -86,6 +86,26 @@ void *os_query_stackBottom() * Determine base address and size of static data segment. */ +version (GNU) +{ +// This is MinGW specific +extern (C) +{ + // TODO: skip the .rdata between .data and .bss? + extern int _data_start__; + extern int _bss_end__; +} + +void os_query_staticdataseg(void **base, uint *nbytes) +{ + *base = cast(void *)&_data_start__; + *nbytes = cast(uint)(cast(char *)&_bss_end__ - cast(char *)&_data_start__); +} + +} +else +{ + extern (C) { extern int _xi_a; // &_xi_a just happens to be start of data segment @@ -99,6 +119,7 @@ void os_query_staticdataseg(void **base, *nbytes = cast(uint)(cast(char *)&_end - cast(char *)&_xi_a); } +} /++++ void os_query_staticdataseg(void **base, uint *nbytes) diff -uNrp dmd-1.004/src/phobos/internal/memset.d gdc-0.22/d/phobos/internal/memset.d --- dmd-1.004/src/phobos/internal/memset.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/internal/memset.d 2006-06-02 05:31:29.000000000 +0200 @@ -21,6 +21,11 @@ * distribution. */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ extern (C) { @@ -42,7 +47,7 @@ short *_memset16(short *p, short value, int *_memset32(int *p, int value, int count) { -version (X86) +version (Asm86) { asm { diff -uNrp dmd-1.004/src/phobos/internal/monitor.c gdc-0.22/d/phobos/internal/monitor.c --- dmd-1.004/src/phobos/internal/monitor.c 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/internal/monitor.c 2006-12-17 06:03:04.000000000 +0100 @@ -6,6 +6,14 @@ // This is written in C because nobody has written a pthreads interface // to D yet. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + +#include "config.h" + #include #include @@ -13,7 +21,7 @@ #if _WIN32 #elif linux -#define USE_PTHREADS 1 +#define PHOBOS_USE_PTHREADS 1 #else #endif @@ -21,7 +29,7 @@ #include #endif -#if USE_PTHREADS +#if PHOBOS_USE_PTHREADS #include #endif @@ -36,7 +44,7 @@ typedef struct Monitor CRITICAL_SECTION mon; #endif -#if USE_PTHREADS +#if PHOBOS_USE_PTHREADS pthread_mutex_t mon; #endif } Monitor; @@ -123,9 +131,12 @@ void _d_monitorrelease(Object *h) /* =============================== linux ============================ */ -#if USE_PTHREADS +// needs to be else.. +#if PHOBOS_USE_PTHREADS -// Includes attribute fixes from David Friedman's GDC port +#ifndef HAVE_PTHREAD_MUTEX_RECURSIVE +#define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP +#endif static pthread_mutex_t _monitor_critsec; static pthread_mutexattr_t _monitors_attr; @@ -133,10 +144,12 @@ static pthread_mutexattr_t _monitors_att void _STI_monitor_staticctor() { if (!inited) - { + { +#ifndef PTHREAD_MUTEX_ALREADY_RECURSIVE pthread_mutexattr_init(&_monitors_attr); - pthread_mutexattr_settype(&_monitors_attr, PTHREAD_MUTEX_RECURSIVE_NP); - pthread_mutex_init(&_monitor_critsec, 0); + pthread_mutexattr_settype(&_monitors_attr, PTHREAD_MUTEX_RECURSIVE); +#endif + pthread_mutex_init(&_monitor_critsec, 0); // the global critical section doesn't need to be recursive inited = 1; } } @@ -145,8 +158,10 @@ void _STD_monitor_staticdtor() { if (inited) { inited = 0; +#ifndef PTHREAD_MUTEX_ALREADY_RECURSIVE pthread_mutex_destroy(&_monitor_critsec); pthread_mutexattr_destroy(&_monitors_attr); +#endif } } @@ -162,7 +177,11 @@ void _d_monitorenter(Object *h) if (!h->monitor) // if, in the meantime, another thread didn't set it { h->monitor = (void *)cs; +#ifndef PTHREAD_MUTEX_ALREADY_RECURSIVE pthread_mutex_init(&cs->mon, & _monitors_attr); +#else + pthread_mutex_init(&cs->mon, NULL); +#endif cs = NULL; } pthread_mutex_unlock(&_monitor_critsec); diff -uNrp dmd-1.004/src/phobos/internal/object.d gdc-0.22/d/phobos/internal/object.d --- dmd-1.004/src/phobos/internal/object.d 2007-01-26 22:58:42.000000000 +0100 +++ gdc-0.22/d/phobos/internal/object.d 2007-02-03 17:34:12.000000000 +0100 @@ -32,6 +32,12 @@ * distribution. */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, April 2005 +*/ + module object; @@ -835,7 +841,13 @@ class TypeInfo_Struct : TypeInfo else if (!p1 || !p2) c = 0; else if (xopEquals) - c = (*xopEquals)(p1, p2); + { + version (GNU) + // GDC and DMD use different calling conventions + c = (*xopEquals)(p2, p1); + else + c = (*xopEquals)(p1, p2); + } else // BUG: relies on the GC not moving objects c = (memcmp(p1, p2, init.length) == 0); @@ -853,7 +865,13 @@ class TypeInfo_Struct : TypeInfo { if (!p2) c = 1; else if (xopCmp) - c = (*xopCmp)(p1, p2); + { + version (GNU) + // GDC and DMD use different calling conventions + c = (*xopCmp)(p2, p1); + else + c = (*xopCmp)(p1, p2); + } else // BUG: relies on the GC not moving objects c = memcmp(p1, p2, init.length); diff -uNrp dmd-1.004/src/phobos/internal/qsort.d gdc-0.22/d/phobos/internal/qsort.d --- dmd-1.004/src/phobos/internal/qsort.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/internal/qsort.d 1970-01-01 01:00:00.000000000 +0100 @@ -1,162 +0,0 @@ -/* - Portions of this file are: - Copyright Prototronics, 1987 - Totem Lake P.O. 8117 - Kirkland, Washington 98034 - (206) 820-1972 - Licensed to Digital Mars. - - June 11, 1987 from Ray Gardner's - Denver, Colorado) public domain version - - Use qsort2.d instead of this file if a redistributable version of - _adSort() is required. -*/ - - -/* -** Sorts an array starting at base, of length nbr_elements, each -** element of size width_bytes, ordered via compare_function; which -** is called as (*comp_fp)(ptr_to_element1, ptr_to_element2) -** and returns < 0 if element1 < element2, 0 if element1 = element2, -** > 0 if element1 > element2. Most of the refinements are due to -** R. Sedgewick. See "Implementing Quicksort Programs", Comm. ACM, -** Oct. 1978, and Corrigendum, Comm. ACM, June 1979. -*/ - -//debug=qsort; // uncomment to turn on debugging printf's - -import std.c.stdio; -import std.c.stdlib; -import std.string; -import std.outofmemory; - -struct Array -{ - int length; - void *ptr; -} - - -private const int _maxspan = 7; // subarrays of _maxspan or fewer elements - // will be sorted by a simple insertion sort - -/* Adjust _maxspan according to relative cost of a swap and a compare. Reduce -_maxspan (not less than 1) if a swap is very expensive such as when you have -an array of large structures to be sorted, rather than an array of pointers to -structures. The default value is optimized for a high cost for compares. */ - - -extern (C) long _adSort(Array a, TypeInfo ti) -{ - byte* base; - byte*[40] stack; // stack - byte** sp; // stack pointer - byte* i, j, limit; // scan and limit pointers - uint thresh; // size of _maxspan elements in bytes - uint width = ti.tsize(); - - base = cast(byte *)a.ptr; - thresh = _maxspan * width; // init threshold - sp = stack.ptr; // init stack pointer - limit = base + a.length * width; // pointer past end of array - while (1) // repeat until done then return - { - while (limit - base > thresh) // if more than _maxspan elements - { - //swap middle, base - ti.swap((cast(uint)(limit - base) >> 1) - - (((cast(uint)(limit - base) >> 1)) % width) + base, base); - - i = base + width; // i scans from left to right - j = limit - width; // j scans from right to left - - if (ti.compare(i, j) > 0) // Sedgewick's - ti.swap(i, j); // three-element sort - if (ti.compare(base, j) > 0) // sets things up - ti.swap(base, j); // so that - if (ti.compare(i, base) > 0) // *i <= *base <= *j - ti.swap(i, base); // *base is the pivot element - - while (1) - { - do // move i right until *i >= pivot - i += width; - while (ti.compare(i, base) < 0); - do // move j left until *j <= pivot - j -= width; - while (ti.compare(j, base) > 0); - if (i > j) // break loop if pointers crossed - break; - ti.swap(i, j); // else swap elements, keep scanning - } - ti.swap(base, j); // move pivot into correct place - if (j - base > limit - i) // if left subarray is larger... - { - sp[0] = base; // stack left subarray base - sp[1] = j; // and limit - base = i; // sort the right subarray - } - else // else right subarray is larger - { - sp[0] = i; // stack right subarray base - sp[1] = limit; // and limit - limit = j; // sort the left subarray - } - sp += 2; // increment stack pointer - assert(sp < cast(byte**)stack + stack.length); - } - - // Insertion sort on remaining subarray - i = base + width; - while (i < limit) - { - j = i; - while (j > base && ti.compare(j - width, j) > 0) - { - ti.swap(j - width, j); - j -= width; - } - i += width; - } - - if (sp > stack.ptr) // if any entries on stack... - { - sp -= 2; // pop the base and limit - base = sp[0]; - limit = sp[1]; - } - else // else stack empty, all done - return *cast(long*)(&a); - } - assert(0); -} - - -unittest -{ - debug(qsort) printf("array.sort.unittest()\n"); - - int a[] = new int[10]; - - a[0] = 23; - a[1] = 1; - a[2] = 64; - a[3] = 5; - a[4] = 6; - a[5] = 5; - a[6] = 17; - a[7] = 3; - a[8] = 0; - a[9] = -1; - - a.sort; - - for (int i = 0; i < a.length - 1; i++) - { - //printf("i = %d", i); - //printf(" %d %d\n", a[i], a[i + 1]); - assert(a[i] <= a[i + 1]); - } -} - diff -uNrp dmd-1.004/src/phobos/internal/qsortg.d gdc-0.22/d/phobos/internal/qsortg.d --- dmd-1.004/src/phobos/internal/qsortg.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/internal/qsortg.d 2006-12-17 06:03:04.000000000 +0100 @@ -0,0 +1,115 @@ + +struct Array +{ + int length; + void * ptr; +} + +extern (C) Array _adSort(Array a, TypeInfo ti) +{ + static const uint Qsort_Threshold = 7; + + struct StackEntry { + byte *l; + byte *r; + } + + size_t elem_size = ti.tsize(); + size_t qsort_limit = elem_size * Qsort_Threshold; + + static assert(ubyte.sizeof == 1); + static assert(ubyte.max == 255); + + StackEntry[size_t.sizeof * 8] stack; // log2( size_t.max ) + StackEntry * sp = stack.ptr; + byte* lbound = cast(byte *) a.ptr; + byte* rbound = cast(byte *) a.ptr + a.length * elem_size; + byte* li = void; + byte* ri = void; + + while (1) + { + if (rbound - lbound > qsort_limit) + { + ti.swap(lbound, + lbound + ( + ((rbound - lbound) >>> 1) - + (((rbound - lbound) >>> 1) % elem_size) + )); + + li = lbound + elem_size; + ri = rbound - elem_size; + + if (ti.compare(li, ri) > 0) + ti.swap(li, ri); + if (ti.compare(lbound, ri) > 0) + ti.swap(lbound, ri); + if (ti.compare(li, lbound) > 0) + ti.swap(li, lbound); + + while (1) + { + do + li += elem_size; + while (ti.compare(li, lbound) < 0); + do + ri -= elem_size; + while (ti.compare(ri, lbound) > 0); + if (li > ri) + break; + ti.swap(li, ri); + } + ti.swap(lbound, ri); + if (ri - lbound > rbound - li) + { + sp.l = lbound; + sp.r = ri; + lbound = li; + } + else + { + sp.l = li; + sp.r = rbound; + rbound = ri; + } + ++sp; + } else { + // Use insertion sort + for (ri = lbound, li = lbound + elem_size; + li < rbound; + ri = li, li += elem_size) + { + for ( ; ti.compare(ri, ri + elem_size) > 0; + ri -= elem_size) + { + ti.swap(ri, ri + elem_size); + if (ri == lbound) + break; + } + } + if (sp != stack.ptr) + { + --sp; + lbound = sp.l; + rbound = sp.r; + } + else + return a; + } + } +} + +unittest +{ + static void check(int[] a) { + for (uint i = 1; i < a.length; i++) + assert(a[i-1] <= a[i]); + } + + static int[] t1 = [ 4, 3, 19, 7, 6, 20, 11, 1, 2, 5 ]; + int[] a; + + a = t1; + a.sort; + check(a); +} diff -uNrp dmd-1.004/src/phobos/internal/rundmain.d gdc-0.22/d/phobos/internal/rundmain.d --- dmd-1.004/src/phobos/internal/rundmain.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/internal/rundmain.d 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,6 @@ +private extern (C) int _d_run_main(int argc, char **argv, void * p); +int main(); +extern (C) int _d_run_Dmain(int argc, char **argv) +{ + return _d_run_main(argc, argv, & main); +} diff -uNrp dmd-1.004/src/phobos/libgphobos.spec.in gdc-0.22/d/phobos/libgphobos.spec.in --- dmd-1.004/src/phobos/libgphobos.spec.in 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/libgphobos.spec.in 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,7 @@ +# +# This spec file is read by gdc when linking. +# It is used to specify the standard libraries we need in order +# to link with libphobos. +# +%rename lib liborig +*lib: @LIBS@ %(liborig) diff -uNrp dmd-1.004/src/phobos/Makefile.in gdc-0.22/d/phobos/Makefile.in --- dmd-1.004/src/phobos/Makefile.in 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/Makefile.in 2007-02-03 18:35:36.000000000 +0100 @@ -0,0 +1,292 @@ +# GDC -- D front-end for GCC +# Copyright (C) 2004 David Friedman +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +target_alias = @target_alias@ +host_alias = @host_alias@ + +AR = @AR@ +RANLIB = @RANLIB@ + +CFLAGS=@CFLAGS@ +OUR_CFLAGS=@DEFS@ -I . -I $(srcdir)/gcc +D_GC_FLAGS=@D_GC_FLAGS@ + +# Because parts of Phobos are generated (and are in flux), we need +# to prevent this build from getting tripped up on an already installed +# version. Add -nostdinc to handle this. + +# Only the GC routines need D_GC_FLAGS + +DFLAGS=@DFLAGS@ $(D_GC_FLAGS) -nostdinc + +D_GENERATE_FRAGMENTS=@D_GENERATE_FRAGMENTS@ +D_FRAGMENT_SRCDIR=@D_FRAGMENT_SRCDIR@ + +EXEEXT=@EXEEXT@ + +INSTALL=@INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_HEADER = $(INSTALL_DATA) +# %% fix when part of normal build process +mkinstalldirs = $(INSTALL) -d + +# %% remove for automake.. +STAMP = echo timestamp > + +# Note that the real gdc knows what LIBS to use +LIBS=@LIBS@ +CC=@CC@ +GDC=@GDC@ + +srcdir=@srcdir@ +VPATH = @srcdir@ + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +phobos_toolexecdir = @phobos_toolexecdir@ +phobos_toolexeclibdir = @phobos_toolexeclibdir@ +toolexecdir = $(phobos_toolexecdir) +toolexeclibdir = $(phobos_toolexeclibdir) + +gdc_include_dir=@gdc_include_dir@ + +config_d_src=$(host_alias)/gcc/config.d +configunix_d_src=$(host_alias)/gcc/configunix.d + +D_PREREQ_SRCS=@D_PREREQ_SRCS@ + +all: libgphobos.a + +%.o : %.c + $(CC) -o $@ $(OUR_CFLAGS) $(CFLAGS) -c $< + +%.o : %.d $(D_PREREQ_SRCS) + $(GDC) -o $@ $(DFLAGS) -I $(srcdir) -I $(srcdir)/internal/gc -I ./$(host_alias) -c $< + +# boxer is currently broken +std/boxer.t.o: std/boxer.o + cp $< $@ + +%.t.o : %.d $(D_PREREQ_SRCS) + $(GDC) -o $@ $(DFLAGS) -fno-release -funittest -I $(srcdir) -I $(srcdir)/internal/gc -I ./$(host_alias) -c $< + +internal/gc/gcx.t.o: $(D_PREREQ_SRCS) $(srcdir)/internal/gc/gcx.d + $(GDC) -o $@ $(DFLAGS) -funittest -I $(srcdir) -I $(srcdir)/internal/gc -I ./$(host_alias) -c $< + +%.t.o : %.o + cp $< $@ + +Makefile: Makefile.in + ./config.status + +unittest: unittest.o libgphobos_t.a libgphobos.a + $(GDC) -o $@ $(CFLAGS) unittest.o -L./ -lgphobos_t $(LIBS) + +internal/gc/testgc.o: $(host_alias)/gcc/config.d $(srcdir)/internal/gc/testgc.d + $(GDC) -o $@ $(DFLAGS) -fno-release -I $(srcdir) -I $(srcdir)/internal/gc -I ./$(host_alias) -c $(srcdir)/internal/gc/testgc.d + +testgc: internal/gc/testgc.o libgphobos_t.a libgphobos.a + $(GDC) -o $@ $(CFLAGS) internal/gc/testgc.o -L./ -lgphobos_t $(LIBS) + +TI=ti_AC.o ti_Ag.o ti_Aint.o ti_Along.o ti_Ashort.o \ + ti_C.o \ + ti_byte.o ti_cdouble.o ti_cfloat.o ti_char.o ti_creal.o \ + ti_dchar.o ti_delegate.o ti_double.o ti_float.o ti_idouble.o ti_ifloat.o \ + ti_int.o ti_ireal.o ti_long.o ti_ptr.o ti_real.o ti_short.o ti_ubyte.o \ + ti_uint.o ti_ulong.o ti_ushort.o ti_wchar.o \ + ti_Afloat.o ti_Adouble.o ti_Areal.o \ + ti_Acfloat.o ti_Acdouble.o ti_Acreal.o \ + ti_void.o + +MAIN_OBJS=std/asserterror.o internal/switch.o gcstats.o \ + internal/critical.o internal/object.o internal/monitor.o internal/arraycat.o internal/invariant.o \ + std/outofmemory.o internal/aaA.o internal/adi.o internal/aApply.o internal/aApplyR.o std/file.o \ + std/compiler.o std/system.o std/moduleinit.o std/md5.o std/base64.o \ + internal/cast.o std/path.o std/string.o internal/memset.o std/math.o std/mmfile.o \ + std/outbuffer.o std/ctype.o std/regexp.o std/random.o \ + std/stream.o std/cstream.o std/switcherr.o std/array.o std/gc.o \ + internal/qsortg.o std/thread.o internal/obj.o std/utf.o std/uri.o \ + crc32.o std/conv.o internal/arraycast.o errno.o \ + std/process.o std/syserror.o \ + std/socket.o std/socketstream.o std/c/stdarg.o std/stdio.o std/format.o \ + std/perf.o std/openrj.o std/uni.o std/demangle.o std/bitarray.o \ + $(subst ti_,std/typeinfo/ti_,$(TI)) \ + std/date.o std/dateparse.o std/math2.o etc/c/zlib.o std/zlib.o std/zip.o \ + internal/dgccmain2.o internal/rundmain.o std/stdarg.o \ + std/signals.o std/cpuid.o std/traits.o std/typetuple.o std/bind.o + +# This should not be linked into a shared library. +CMAIN_OBJS=internal/cmain.o + +ZLIB_OBJS= etc/c/zlib/adler32.o etc/c/zlib/compress.o \ + etc/c/zlib/crc32.o etc/c/zlib/gzio.o \ + etc/c/zlib/uncompr.o etc/c/zlib/deflate.o \ + etc/c/zlib/trees.o etc/c/zlib/zutil.o \ + etc/c/zlib/inflate.o etc/c/zlib/infback.o \ + etc/c/zlib/inftrees.o etc/c/zlib/inffast.o + +GC_OBJS= internal/gc/gc.o internal/gc/gcx.o \ + internal/gc/gcbits.o +GC_OBJS += @D_GC_MODULES@ + +GCC_OBJS = gcc/config.o gcc/unwind.o gcc/deh.o gcc/threadsem.o \ + std/c/dirent.o gcc/cbridge_time.o + +# std.c.linux.linux, std.loader, gcc.cbridge* +WINDOWS_OBJS=std/c/windows/windows.o std/c/windows/com.o std/c/windows/winsock.o \ + std/windows/iunknown.o std/windows/registry.o std/windows/syserror.o \ + std/windows/charset.o +D_EXTRA_OBJS=@D_EXTRA_OBJS@ + +# needed until instrinsics are implemented +D_EXTRA_OBJS+=std/intrinsic.o + +# currently just add compatibility for a bug +D_EXTRA_OBJS+=gcc/support.o + +CONFIG_D_FRAGMENTS = config/config-head frag-ac frag-gen frag-math config/config-mid config/config-tail +CONFIG_UNIX_FRAGMENTS = config/unix-head frag-unix config/unix-mid + +# until I figure out how to deal with weak module references +WEAK_OBJS = + +# This has to be an empty file because it is included in the prerequisites of rules +# that use "cat $^" to generate their targets. +# Otherwise, need to specify $srcdir for known source files in CONFIG_xxx_FRAGMENTS.. +stamp-tgtdir: + mkdir -p $(host_alias)/gcc + touch $@ + +gen_config1: config/gen_config1.o + $(CC) -o $@ $^ + +$(config_d_src): $(CONFIG_D_FRAGMENTS) stamp-tgtdir + cat $^ > $@ + +gcc/config.o: $(config_d_src) + $(GDC) -o $@ $(DFLAGS) -I $(srcdir) -I $(srcdir)/internal/gc -I ./$(host_alias) -c $< +gcc/config.t.o: gcc/config.o + cp gcc/config.o gcc/config.t.o + + +gen_math: config/gen_math.o + $(CC) -o $@ $^ + +config/gen_unix.o: config/gen_unix.c config/makestruct.h + +gen_unix: config/gen_unix.o + $(CC) -o $@ $^ + +ifdef D_GENERATE_FRAGMENTS +frag-gen: gen_config1 + ./gen_config1 > $@ || rm -f $@ +frag-unix: gen_unix + ./gen_unix > $@ +frag-math: gen_math + ./gen_math > $@ || rm -f $@ +else +frag-gen: $(D_FRAGMENT_SRCDIR)/$@ + cp $(D_FRAGMENT_SRCDIR)/$@ $@ +frag-unix: $(D_FRAGMENT_SRCDIR)/$@ + cp $(D_FRAGMENT_SRCDIR)/$@ $@ +frag-math: $(D_FRAGMENT_SRCDIR)/$@ + cp $(D_FRAGMENT_SRCDIR)/$@ $@ +endif + +$(configunix_d_src): $(CONFIG_UNIX_FRAGMENTS) stamp-tgtdir + cat $^ > $@ + +gcc/configunix.o: $(configunix_d_src) $(config_d_src) + $(GDC) -o $@ $(DFLAGS) -I $(srcdir) -I $(srcdir)/internal/gc -I ./$(host_alias) -c $< +gcc/configunix.t.o: gcc/configunix.o + cp gcc/configunix.o gcc/configunix.t.o + +gcc/cbridge_math.o: gcc/cbridge_math.c + $(CC) -o $@ $(OUR_CFLAGS) $(CFLAGS) -fno-strict-aliasing -c $< + +std/stream.o: std/stream.d $(D_PREREQ_SRCS) + $(GDC) -o $@ $(DFLAGS) -fdeprecated -I $(srcdir) -I $(srcdir)/internal/gc -I ./$(host_alias) -c $< +std/stream.t.o: std/stream.d $(D_PREREQ_SRCS) + $(GDC) -o $@ $(DFLAGS) -fdeprecated -I $(srcdir) -I $(srcdir)/internal/gc -I ./$(host_alias) -c $< + + + +# GCC_OBJS (gcc/config.o) first so I don't have to write more deps +ALL_PHOBOS_OBJS = $(D_EXTRA_OBJS) $(GCC_OBJS) $(MAIN_OBJS) $(ZLIB_OBJS) $(GC_OBJS) $(WEAK_OBJS) + +libgphobos.a : $(ALL_PHOBOS_OBJS) $(CMAIN_OBJS) + $(AR) -r $@ $(ALL_PHOBOS_OBJS) $(CMAIN_OBJS) + $(RANLIB) $@ + +libgphobos_t.a : $(ALL_PHOBOS_OBJS:.o=.t.o) $(CMAIN_OBJS) + $(AR) -r $@ $(ALL_PHOBOS_OBJS:.o=.t.o) $(CMAIN_OBJS) + $(RANLIB) $@ + +.PHONY: info dvi TAGS install-info installcheck mostlyclean distclean maintainer-clean check + +check: unittest testgc + ./unittest + ./testgc + +info: +dvi: +TAGS: +install-info: +installcheck: +mostlyclean: clean +distclean: clean +maintainer-clean: clean + +#echo "XXX" $(mkinstalldirs) $(DESTDIR)$(gdc_include_dir)/$$i; \ +#echo "YYY" $(INSTALL_HEADER) $(srcdir)/$$i/*.[hd] $(DESTDIR)$(gdc_include_dir)/$$i; \ + +# 3.3.x install-sh can't handle multiple source arguments +# $(INSTALL_HEADER) $(srcdir)/$$i/*.[hd] $(DESTDIR)$(gdc_include_dir)/$$i; done +install: $(D_PREREQ_SRCS) libgphobos.a + for i in etc etc/c \ + etc/c/zlib \ + gcc std std/c \ + std/c/darwin std/c/linux std/c/mach std/c/skyos std/c/unix std/c/windows \ + std/typeinfo std/windows; do \ + $(mkinstalldirs) $(DESTDIR)$(gdc_include_dir)/$$i; \ + for f in $(srcdir)/$$i/*.[hd]; do $(INSTALL_HEADER) $$f $(DESTDIR)$(gdc_include_dir)/$$i; done; \ + done + for i in crc32.d gcstats.d object.d; do \ + $(INSTALL_HEADER) $(srcdir)/$$i $(DESTDIR)$(gdc_include_dir); done + $(mkinstalldirs) $(DESTDIR)$(gdc_include_dir)/$(host_alias)/gcc + $(INSTALL_HEADER) $(config_d_src) $(DESTDIR)$(gdc_include_dir)/$(host_alias)/gcc + if test -f $(configunix_d_src); then $(INSTALL_HEADER) $(host_alias)/gcc/configunix.d $(DESTDIR)$(gdc_include_dir)/$(host_alias)/gcc; fi + $(INSTALL) phobos-ver-syms $(DESTDIR)$(gdc_include_dir)/$(host_alias) + $(mkinstalldirs) $(DESTDIR)$(toolexeclibdir) + $(INSTALL) libgphobos.a $(DESTDIR)$(toolexeclibdir) + $(RANLIB) $(DESTDIR)$(toolexeclibdir)/libgphobos.a + $(INSTALL) libgphobos.spec $(DESTDIR)$(toolexeclibdir) + +clean: + rm -f $(ALL_PHOBOS_OBJS) $(CMAIN_OBJS) + rm -f $(ALL_PHOBOS_OBJS:.o=.t.o) + rm -f unittest.o internal/gc/testgc.o + rm -f unittest$(EXEEXT) testgc$(EXEEXT) + rm -f config/gen_config1.o config/gen_unix.o config/gen_math.o + rm -f gen_config1$(EXEEXT) gen_unix$(EXEEXT) gen_math$(EXEEXT) + rm -f frag-gen frag-math frag-unix + rm -f $(config_d_src) $(configunix_d_src) + rm -f libgphobos.a + rm -f libgphobos_t.a diff -uNrp dmd-1.004/src/phobos/phobos-ver-syms.in gdc-0.22/d/phobos/phobos-ver-syms.in --- dmd-1.004/src/phobos/phobos-ver-syms.in 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/phobos-ver-syms.in 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,17 @@ +@DCFG_UNIX@ +@DCFG_PTHREAD_SUSPEND@ +@DCFG_SEMAPHORE_IMPL@ +@DCFG_TRUNC@ +@DCFG_NEARBYINT@ +@DCFG_ROUND@ +@DCFG_TGAMMA@ +@DCFG_NAN@ +@DCFG_EXP2_LOG2@ +@DCFG_EXECVPE@ +@DCFG_SPAWNVP@ +@DCFG_FWIDE@ +@DCFG_STRTOLD@ +@DCFG_SA_LEN@ +@DCFG_CBRIDGE_STDIO@ +@DCFG_MMAP@ +@DCFG_GETPWNAM_R@ diff -uNrp dmd-1.004/src/phobos/std/bitarray.d gdc-0.22/d/phobos/std/bitarray.d --- dmd-1.004/src/phobos/std/bitarray.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/bitarray.d 2007-01-27 17:44:01.000000000 +0100 @@ -291,19 +291,19 @@ struct BitArray if (this.length != a2.length) return 0; // not equal - byte *p1 = cast(byte*)this.ptr; - byte *p2 = cast(byte*)a2.ptr; - uint n = this.length / 8; + uint *p1 = cast(uint*)this.ptr; + uint *p2 = cast(uint*)a2.ptr; + uint n = this.length / (8 * uint.sizeof); for (i = 0; i < n; i++) { if (p1[i] != p2[i]) return 0; // not equal } - ubyte mask; + uint mask; - n = this.length & 7; - mask = cast(ubyte)((1 << n) - 1); + n = this.length & ((8 * uint.sizeof) - 1); + mask = (1 << n) - 1; //printf("i = %d, n = %d, mask = %x, %x, %x\n", i, n, mask, p1[i], p2[i]); return (mask == 0) || (p1[i] & mask) == (p2[i] & mask); } @@ -342,14 +342,15 @@ struct BitArray len = this.length; if (a2.length < len) len = a2.length; - ubyte* p1 = cast(ubyte*)this.ptr; - ubyte* p2 = cast(ubyte*)a2.ptr; - uint n = len / 8; + uint* p1 = cast(uint*)this.ptr; + uint* p2 = cast(uint*)a2.ptr; + uint n = len / (8 * uint.sizeof); for (i = 0; i < n; i++) { if (p1[i] != p2[i]) break; // not equal } + /* for (uint j = i * 8; j < len; j++) { ubyte mask = cast(ubyte)(1 << j); int c; @@ -358,6 +359,16 @@ struct BitArray if (c) return c; } + */ + uint mask = 1; + for (uint j = i * (8 * uint.sizeof); j < len; j++) + { int c; + + c = cast(int)(p1[i] & mask) - cast(int)(p2[i] & mask); + if (c) + return c; + mask <<= 1; + } return cast(int)this.len - cast(int)a2.length; } diff -uNrp dmd-1.004/src/phobos/std/boxer.d gdc-0.22/d/phobos/std/boxer.d --- dmd-1.004/src/phobos/std/boxer.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/boxer.d 2006-12-17 06:03:04.000000000 +0100 @@ -57,11 +57,21 @@ a = boxArray(arg_types, arg_data); * WIKI=Phobos/StdBoxer */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, May 2005 + + This module make not work on all GCC targets due to assumptions + about the type of va_list. +*/ module std.boxer; private import std.format; private import std.string; private import std.utf; +version (GNU) + private import std.stdarg; /* These functions and types allow packing objects into generic containers * and recovering them later. This comes into play in a wide spectrum of @@ -133,6 +143,11 @@ private enum TypeClass Other, /**< Any other type, such as delegates, function pointers, struct, void... */ } +version (DigitalMars) + version = DigitalMars_TypeInfo; +else version (GNU) + version = DigitalMars_TypeInfo; + /** * Box is a generic container for objects (both value and heap), allowing the * user to box them in a generic form and recover them later. @@ -150,7 +165,7 @@ struct Box void* p_longData; /**< An array of the contained object. */ void[8] p_shortData; /**< Data used when the object is small. */ } - + private static TypeClass findTypeClass(TypeInfo type) { if (cast(TypeInfo_Class) type) @@ -160,7 +175,7 @@ struct Box if (isArrayTypeInfo(type)) return TypeClass.Array; - version (DigitalMars) + version (DigitalMars_TypeInfo) { /* Depend upon the name of the base type classes. */ if (type.classinfo.name.length != "TypeInfo_?".length) @@ -276,7 +291,13 @@ struct Box args[0..(char[]).sizeof] = (cast(void*) &format)[0..(char[]).sizeof]; args[(char[]).sizeof..length] = data; - std.format.doFormat(&putc, arguments, args.ptr); + version (GNU) + { + va_list dummy = void; + std.format.doFormat(&putc, arguments, dummy, args.ptr); + } + else + std.format.doFormat(&putc, arguments, args.ptr); delete args; return string; @@ -400,7 +421,7 @@ in } body { - return box(_arguments[0], _argptr); + return box(_arguments[0], cast(void*) _argptr); } /** @@ -449,17 +470,17 @@ Box[] boxArray(TypeInfo[] types, void* d return array; } -/** - * Box each argument passed to the function, returning an array of boxes. - */ + /** + * Box each argument passed to the function, returning an array of boxes. + */ Box[] boxArray(...) { - return boxArray(_arguments, _argptr); + return boxArray(_arguments, cast(void *) _argptr); } -/** - * Convert an array of boxes into an array of arguments. - */ + /** + * Convert an array of boxes into an array of arguments. + */ void boxArrayToArguments(Box[] arguments, out TypeInfo[] types, out void* data) { size_t dataLength; @@ -706,7 +727,7 @@ template unbox(T : void*) return *cast(void**) value.data; if (isArrayTypeInfo(value.type)) return (*cast(void[]*) value.data).ptr; - if (typeid(Object) == value.type) + if (cast(TypeInfo_Class) value.type) return *cast(Object*) value.data; throw new UnboxException(value, typeid(T)); diff -uNrp dmd-1.004/src/phobos/std/c/darwin/darwin.d gdc-0.22/d/phobos/std/c/darwin/darwin.d --- dmd-1.004/src/phobos/std/c/darwin/darwin.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/darwin/darwin.d 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,170 @@ +/* GDC -- D front-end for GCC + Copyright (C) 2004 David Friedman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +module std.c.darwin.darwin; + +import gcc.configunix; + +/+ +alias int time_t; +alias long off_t; + +enum : int +{ + SIGHUP = 1, + SIGINT = 2, + SIGQUIT = 3, + SIGILL = 4, + SIGTRAP = 5, + SIGABRT = 6, + SIGIOT = SIGABRT, + SIGEMT = 7, + SIGFPE = 8, + SIGKILL = 9, + SIGBUS = 10, + SIGSEGV = 11, + SIGSYS = 12, + SIGPIPE = 13, + SIGALRM = 14, + SIGTERM = 15, + SIGURG = 16, + SIGSTOP = 17, + SIGTSTP = 18, + SIGCONT = 19, + SIGCHLD = 20, + SIGTTIN = 21, + SIGTTOU = 22, + SIGIO = 23, + SIGXCPU = 24, + SIGXFSZ = 25, + SIGVTALRM = 26, + SIGPROF = 27, + SIGWINCH = 28, + SIGINFO = 29, + SIGUSR1 = 30, + SIGUSR2 = 31 +} + +enum +{ + O_RDONLY = 0x0000, + O_WRONLY = 0x0001, + O_RDWR = 0x0002, + O_ACCMODE = 0x0003, + O_NONBLOCK = 0x0004, + O_APPEND = 0x0008, + O_SHLOCK = 0x0010, + O_EXLOCK = 0x0020, + O_ASYNC = 0x0040, + O_FSYNC = 0x0080, + O_NOFOLLOW = 0x0100, + O_CREAT = 0x0200, + O_TRUNC = 0x0400, + O_EXCL = 0x0800 + +} + +struct timespec { + time_t tv_sec; /* seconds */ + int tv_nsec; /* and nanoseconds */ +}; + +struct struct_stat { + int st_dev; /* inode's device */ + uint st_ino; /* inode's number */ + ushort st_mode; /* inode protection mode */ + ushort st_nlink; /* number of hard links */ + uint st_uid; /* user ID of the file's owner */ + uint st_gid; /* group ID of the file's group */ + int st_rdev; /* device type */ + version (None) { // #ifndef _POSIX_SOURCE + timespec st_atimespec; /* time of last access */ + timespec st_mtimespec; /* time of last data modification */ + timespec st_ctimespec; /* time of last file status change */ + } else { + time_t st_atime; /* time of last access */ + int st_atimensec; /* nsec of last access */ + time_t st_mtime; /* time of last data modification */ + int st_mtimensec; /* nsec of last data modification */ + time_t st_ctime; /* time of last file status change */ + int st_ctimensec; /* nsec of last file status change */ + } + off_t st_size; /* file size, in bytes */ + long st_blocks; /* blocks allocated for file */ + uint st_blksize; /* optimal blocksize for I/O */ + uint st_flags; /* user defined flags for file */ + uint st_gen; /* file generation number */ + int st_lspare; + long st_qspare[2]; +}; + +enum : int +{ + S_IFIFO = 0010000, + S_IFCHR = 0020000, + S_IFDIR = 0040000, + S_IFBLK = 0060000, + S_IFREG = 0100000, + S_IFLNK = 0120000, + S_IFSOCK = 0140000, + + S_IFMT = 0170000 +} + +extern (C) +{ + int open(char*, int, ...); + int read(int, void*, size_t); + int write(int, void*, size_t); + int close(int); + off_t lseek(int, off_t, int); + int fstat(int, struct_stat*); + int stat(char*, struct_stat*); + int getErrno(); + int chdir(char*); + int mkdir(char*, int); + int rmdir(char*); + char* getcwd(char*, int); +} + +struct timeval { + int tv_sec; /* seconds */ + int tv_usec; /* and microseconds */ +}; + +struct tm { + int tm_sec; /* seconds after the minute [0-60] */ + int tm_min; /* minutes after the hour [0-59] */ + int tm_hour; /* hours since midnight [0-23] */ + int tm_mday; /* day of the month [1-31] */ + int tm_mon; /* months since January [0-11] */ + int tm_year; /* years since 1900 */ + int tm_wday; /* days since Sunday [0-6] */ + int tm_yday; /* days since January 1 [0-365] */ + int tm_isdst; /* Daylight Savings Time flag */ + int tm_gmtoff; /* offset from CUT in seconds */ + char *tm_zone; /* timezone abbreviation */ +}; + +extern (C) +{ + int gettimeofday(timeval*, void*); + time_t time(time_t*); + tm *localtime(time_t*); +} ++/ diff -uNrp dmd-1.004/src/phobos/std/c/darwin/ldblcompat.d gdc-0.22/d/phobos/std/c/darwin/ldblcompat.d --- dmd-1.004/src/phobos/std/c/darwin/ldblcompat.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/darwin/ldblcompat.d 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,39 @@ +/* In C, the stdio/stdlib function to use are determined by a test in cdefs.h. + There is another test for math functions in architecture/ppc/math.h which + is reproduced, in spirit, here. This one test controls both stdio/stdlib and + math functions for D. */ + +module std.c.darwin.ldblcompat; + +version (PPC) +{ + version (GNU_WantLongDoubleFormat128) + version = GNU_UseLongDoubleFormat128; + else version (GNU_WantLongDoubleFormat64) + { } + else + { + version (GNU_LongDouble128) + version = GNU_UseLongDoubleFormat128; + } +} + +version (GNU_UseLongDoubleFormat128) +{ + // Currently, the following test from cdefs.h is not supported: + //# if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0 < 1040 + version (all) + const char[] __DARWIN_LDBL_COMPAT = "$LDBL128"; + else + const char[] __DARWIN_LDBL_COMPAT = "$LDBLStub"; + const char[] __DARWIN_LDBL_COMPAT2 = "$LDBL128"; + + const char[] __LIBMLDBL_COMPAT = "$LDBL128"; +} +else +{ + const char[] __DARWIN_LDBL_COMPAT = ""; + const char[] __DARWIN_LDBL_COMPAT2 = ""; + + const char[] __LIBMLDBL_COMPAT = ""; +} diff -uNrp dmd-1.004/src/phobos/std/c/dirent.d gdc-0.22/d/phobos/std/c/dirent.d --- dmd-1.004/src/phobos/std/c/dirent.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/dirent.d 2006-12-17 06:03:04.000000000 +0100 @@ -0,0 +1,53 @@ +/* GDC -- D front-end for GCC + Copyright (C) 2004 David Friedman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +module std.c.dirent; + +private import gcc.config; +private import std.string; +private import gcc.config; + +extern(C) { + +struct dirent { + byte[gcc.config.dirent_d_name_offset] opaque1; + char[gcc.config.dirent_d_name_size] d_name; + byte[gcc.config.dirent_remaining_size] opaque2; +} + +struct DIR { + byte[gcc.config.DIR_struct_size] opaque; +} + +DIR * opendir(char *); +dirent * readdir(DIR *); +void rewinddir(DIR *); +int closedir(DIR *); +Coff_t telldir(DIR* dir); +void seekdir(DIR* dir, Coff_t offset); + +} + +char[] readdirD(DIR * dir) +{ + dirent* ent = readdir(dir); + if (ent) + return toString(ent.d_name.ptr); + else + return null; +} diff -uNrp dmd-1.004/src/phobos/std/c/linux/ldblcompat.d gdc-0.22/d/phobos/std/c/linux/ldblcompat.d --- dmd-1.004/src/phobos/std/c/linux/ldblcompat.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/linux/ldblcompat.d 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,25 @@ +/* In C, the stdio/stdlib function to use are determined by a test in cdefs.h. + Not exactly sure how math funcs are handled. */ + +module std.c.linux.ldblcompat; + +version (GNU_WantLongDoubleFormat128) + version = GNU_UseLongDoubleFormat128; +else version (GNU_WantLongDoubleFormat64) + { } +else +{ + version (GNU_LongDouble128) + version = GNU_UseLongDoubleFormat128; +} + +version (GNU_UseLongDoubleFormat128) +{ + static const bool __No_Long_Double_Math = false; + const char[] __LDBL_COMPAT_PFX = ""; +} +else +{ + static const bool __No_Long_Double_Math = true; + const char[] __LDBL_COMPAT_PFX = "__nldbl_"; +} diff -uNrp dmd-1.004/src/phobos/std/c/linux/linux.d gdc-0.22/d/phobos/std/c/linux/linux.d --- dmd-1.004/src/phobos/std/c/linux/linux.d 2007-01-26 22:58:42.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/linux/linux.d 2006-12-17 06:03:04.000000000 +0100 @@ -1,397 +1,10 @@ - -/* Written by Walter Bright, Christopher E. Miller, and many others. - * www.digitalmars.com - * Placed into public domain. - * Linux(R) is the registered trademark of Linus Torvalds in the U.S. and other - * countries. - */ +// This is a backwards compatibility module for the DMD std.c.linux.linux module std.c.linux.linux; +public import std.c.unix.unix; +public import std.c.dirent; public import std.c.linux.linuxextern; -public import std.c.linux.pthread; - -private import std.c.stdio; - -alias int pid_t; -alias int off_t; -alias uint mode_t; - -alias uint uid_t; -alias uint gid_t; - -enum : int -{ - SIGHUP = 1, - SIGINT = 2, - SIGQUIT = 3, - SIGILL = 4, - SIGTRAP = 5, - SIGABRT = 6, - SIGIOT = 6, - SIGBUS = 7, - SIGFPE = 8, - SIGKILL = 9, - SIGUSR1 = 10, - SIGSEGV = 11, - SIGUSR2 = 12, - SIGPIPE = 13, - SIGALRM = 14, - SIGTERM = 15, - SIGSTKFLT = 16, - SIGCHLD = 17, - SIGCONT = 18, - SIGSTOP = 19, - SIGTSTP = 20, - SIGTTIN = 21, - SIGTTOU = 22, - SIGURG = 23, - SIGXCPU = 24, - SIGXFSZ = 25, - SIGVTALRM = 26, - SIGPROF = 27, - SIGWINCH = 28, - SIGPOLL = 29, - SIGIO = 29, - SIGPWR = 30, - SIGSYS = 31, - SIGUNUSED = 31, -} - -enum -{ - O_RDONLY = 0, - O_WRONLY = 1, - O_RDWR = 2, - O_CREAT = 0100, - O_EXCL = 0200, - O_TRUNC = 01000, - O_APPEND = 02000, -} - -struct struct_stat // distinguish it from the stat() function -{ - ulong st_dev; /// device - ushort __pad1; - uint st_ino; /// file serial number - uint st_mode; /// file mode - uint st_nlink; /// link count - uint st_uid; /// user ID of file's owner - uint st_gid; /// user ID of group's owner - ulong st_rdev; /// if device then device number - ushort __pad2; - int st_size; /// file size in bytes - int st_blksize; /// optimal I/O block size - int st_blocks; /// number of allocated 512 byte blocks - int st_atime; - uint st_atimensec; - int st_mtime; - uint st_mtimensec; - int st_ctime; - uint st_ctimensec; - - uint __unused4; - uint __unused5; -} - -unittest -{ - assert(struct_stat.sizeof == 88); -} - -enum : int -{ - S_IFIFO = 0010000, - S_IFCHR = 0020000, - S_IFDIR = 0040000, - S_IFBLK = 0060000, - S_IFREG = 0100000, - S_IFLNK = 0120000, - S_IFSOCK = 0140000, - - S_IFMT = 0170000, - - S_IREAD = 0000400, - S_IWRITE = 0000200, - S_IEXEC = 0000100, -} - -extern (C) -{ - int access(char*, int); - int open(char*, int, ...); - int read(int, void*, int); - int write(int, void*, int); - int close(int); - int lseek(int, int, int); - int fstat(int, struct_stat*); - int lstat(char*, struct_stat*); - int stat(char*, struct_stat*); - int chdir(char*); - int mkdir(char*, int); - int rmdir(char*); - char* getcwd(char*, int); - int chmod(char*, mode_t); - int fork(); - int dup(int); - int dup2(int, int); - int pipe(int[2]); - pid_t wait(int*); - int waitpid(pid_t, int*, int); - - uint alarm(uint); - char* basename(char*); - //wint_t btowc(int); - int chown(char*, uid_t, gid_t); - int chroot(char*); - size_t confstr(int, char*, size_t); - int creat(char*, mode_t); - char* ctermid(char*); - int dirfd(DIR*); - char* dirname(char*); - int fattach(int, char*); - int fchmod(int, mode_t); - int fdatasync(int); - int ffs(int); - int fmtmsg(int, char*, int, char*, char*, char*); - int fpathconf(int, int); - int fseeko(FILE*, off_t, int); - off_t ftello(FILE*); - - extern char** environ; -} - -struct timeval -{ - int tv_sec; - int tv_usec; -} - -struct struct_timezone -{ - int tz_minuteswest; - int tz_dstime; -} - -struct tm -{ - int tm_sec; - int tm_min; - int tm_hour; - int tm_mday; - int tm_mon; - int tm_year; - int tm_wday; - int tm_yday; - int tm_isdst; - int tm_gmtoff; - int tm_zone; -} - -extern (C) -{ - int gettimeofday(timeval*, struct_timezone*); - __time_t time(__time_t*); - char* asctime(tm*); - char* ctime(__time_t*); - tm* gmtime(__time_t*); - tm* localtime(__time_t*); - __time_t mktime(tm*); - char* asctime_r(tm* t, char* buf); - char* ctime_r(__time_t* timep, char* buf); - tm* gmtime_r(__time_t* timep, tm* result); - tm* localtime_r(__time_t* timep, tm* result); -} - -/**************************************************************/ -// Memory mapping from and - -enum -{ - PROT_NONE = 0, - PROT_READ = 1, - PROT_WRITE = 2, - PROT_EXEC = 4, -} - -// Memory mapping sharing types - -enum -{ MAP_SHARED = 1, - MAP_PRIVATE = 2, - MAP_TYPE = 0x0F, - MAP_FIXED = 0x10, - MAP_FILE = 0, - MAP_ANONYMOUS = 0x20, - MAP_ANON = 0x20, - MAP_GROWSDOWN = 0x100, - MAP_DENYWRITE = 0x800, - MAP_EXECUTABLE = 0x1000, - MAP_LOCKED = 0x2000, - MAP_NORESERVE = 0x4000, - MAP_POPULATE = 0x8000, - MAP_NONBLOCK = 0x10000, -} - -// Values for msync() - -enum -{ MS_ASYNC = 1, - MS_INVALIDATE = 2, - MS_SYNC = 4, -} - -// Values for mlockall() - -enum -{ - MCL_CURRENT = 1, - MCL_FUTURE = 2, -} - -// Values for mremap() - -enum -{ - MREMAP_MAYMOVE = 1, -} - -// Values for madvise - -enum -{ MADV_NORMAL = 0, - MADV_RANDOM = 1, - MADV_SEQUENTIAL = 2, - MADV_WILLNEED = 3, - MADV_DONTNEED = 4, -} - -extern (C) -{ -void* mmap(void*, size_t, int, int, int, off_t); -const void* MAP_FAILED = cast(void*)-1; - -int munmap(void*, size_t); -int mprotect(void*, size_t, int); -int msync(void*, size_t, int); -int madvise(void*, size_t, int); -int mlock(void*, size_t); -int munlock(void*, size_t); -int mlockall(int); -int munlockall(); -void* mremap(void*, size_t, size_t, int); -int mincore(void*, size_t, ubyte*); -int remap_file_pages(void*, size_t, int, size_t, int); -int shm_open(char*, int, int); -int shm_unlink(char*); -} - -extern(C) -{ - - enum - { - DT_UNKNOWN = 0, - DT_FIFO = 1, - DT_CHR = 2, - DT_DIR = 4, - DT_BLK = 6, - DT_REG = 8, - DT_LNK = 10, - DT_SOCK = 12, - DT_WHT = 14, - } - - struct dirent - { - int d_ino; - off_t d_off; - ushort d_reclen; - ubyte d_type; - char[256] d_name; - } - - struct DIR - { - // Managed by OS. - } - - DIR* opendir(char* name); - int closedir(DIR* dir); - dirent* readdir(DIR* dir); - void rewinddir(DIR* dir); - off_t telldir(DIR* dir); - void seekdir(DIR* dir, off_t offset); -} - - -extern(C) -{ - private import std.intrinsic; - - - int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* errorfds, timeval* timeout); - int fcntl(int s, int f, ...); - - - enum - { - EINTR = 4, - EINPROGRESS = 115, - } - - - const uint FD_SETSIZE = 1024; - //const uint NFDBITS = 8 * int.sizeof; // DMD 0.110: 8 * (int).sizeof is not an expression - const int NFDBITS = 32; - - - struct fd_set - { - int[FD_SETSIZE / NFDBITS] fds_bits; - alias fds_bits __fds_bits; - } - - - int FDELT(int d) - { - return d / NFDBITS; - } - - - int FDMASK(int d) - { - return 1 << (d % NFDBITS); - } - - - // Removes. - void FD_CLR(int fd, fd_set* set) - { - btr(cast(uint*)&set.fds_bits.ptr[FDELT(fd)], cast(uint)(fd % NFDBITS)); - } - - - // Tests. - int FD_ISSET(int fd, fd_set* set) - { - return bt(cast(uint*)&set.fds_bits.ptr[FDELT(fd)], cast(uint)(fd % NFDBITS)); - } - - - // Adds. - void FD_SET(int fd, fd_set* set) - { - bts(cast(uint*)&set.fds_bits.ptr[FDELT(fd)], cast(uint)(fd % NFDBITS)); - } - - - // Resets to zero. - void FD_ZERO(fd_set* set) - { - set.fds_bits[] = 0; - } -} extern (C) { @@ -406,71 +19,3 @@ extern (C) void* dlsym(void* handle, char* name); char* dlerror(); } - -extern (C) -{ - /* from - */ - - struct passwd - { - char *pw_name; - char *pw_passwd; - uid_t pw_uid; - gid_t pw_gid; - char *pw_gecos; - char *pw_dir; - char *pw_shell; - } - - const size_t _SIGSET_NWORDS = 1024 / (8 * uint.sizeof); - struct sigset_t - { - uint[_SIGSET_NWORDS] __val; - } - - int getpwnam_r(char*, passwd*, void*, size_t, passwd**); - passwd* getpwnam(char*); - passwd* getpwuid(uid_t); - int getpwuid_r(uid_t, passwd*, char*, size_t, passwd**); - int kill(pid_t, int); - int sem_close(sem_t*); - int sigemptyset(sigset_t*); - int sigfillset(sigset_t*); - int sigismember(sigset_t*, int); - int sigsuspend(sigset_t*); -} - -extern (C) -{ - /* from semaphore.h - */ - - struct sem_t - { - _pthread_fastlock __sem_lock; - int __sem_value; - void* __sem_waiting; - } - - int sem_init(sem_t*, int, uint); - int sem_wait(sem_t*); - int sem_trywait(sem_t*); - int sem_post(sem_t*); - int sem_getvalue(sem_t*, int*); - int sem_destroy(sem_t*); -} - -extern (C) -{ - /* from utime.h - */ - - struct utimbuf - { - __time_t actime; - __time_t modtime; - } - - int utime(char* filename, utimbuf* buf); -} diff -uNrp dmd-1.004/src/phobos/std/c/linux/linux.d.orig-dmd gdc-0.22/d/phobos/std/c/linux/linux.d.orig-dmd --- dmd-1.004/src/phobos/std/c/linux/linux.d.orig-dmd 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/linux/linux.d.orig-dmd 2007-02-03 17:34:12.000000000 +0100 @@ -0,0 +1,476 @@ + +/* Written by Walter Bright, Christopher E. Miller, and many others. + * www.digitalmars.com + * Placed into public domain. + * Linux(R) is the registered trademark of Linus Torvalds in the U.S. and other + * countries. + */ + +module std.c.linux.linux; + +public import std.c.linux.linuxextern; +public import std.c.linux.pthread; + +private import std.c.stdio; + +alias int pid_t; +alias int off_t; +alias uint mode_t; + +alias uint uid_t; +alias uint gid_t; + +enum : int +{ + SIGHUP = 1, + SIGINT = 2, + SIGQUIT = 3, + SIGILL = 4, + SIGTRAP = 5, + SIGABRT = 6, + SIGIOT = 6, + SIGBUS = 7, + SIGFPE = 8, + SIGKILL = 9, + SIGUSR1 = 10, + SIGSEGV = 11, + SIGUSR2 = 12, + SIGPIPE = 13, + SIGALRM = 14, + SIGTERM = 15, + SIGSTKFLT = 16, + SIGCHLD = 17, + SIGCONT = 18, + SIGSTOP = 19, + SIGTSTP = 20, + SIGTTIN = 21, + SIGTTOU = 22, + SIGURG = 23, + SIGXCPU = 24, + SIGXFSZ = 25, + SIGVTALRM = 26, + SIGPROF = 27, + SIGWINCH = 28, + SIGPOLL = 29, + SIGIO = 29, + SIGPWR = 30, + SIGSYS = 31, + SIGUNUSED = 31, +} + +enum +{ + O_RDONLY = 0, + O_WRONLY = 1, + O_RDWR = 2, + O_CREAT = 0100, + O_EXCL = 0200, + O_TRUNC = 01000, + O_APPEND = 02000, +} + +struct struct_stat // distinguish it from the stat() function +{ + ulong st_dev; /// device + ushort __pad1; + uint st_ino; /// file serial number + uint st_mode; /// file mode + uint st_nlink; /// link count + uint st_uid; /// user ID of file's owner + uint st_gid; /// user ID of group's owner + ulong st_rdev; /// if device then device number + ushort __pad2; + int st_size; /// file size in bytes + int st_blksize; /// optimal I/O block size + int st_blocks; /// number of allocated 512 byte blocks + int st_atime; + uint st_atimensec; + int st_mtime; + uint st_mtimensec; + int st_ctime; + uint st_ctimensec; + + uint __unused4; + uint __unused5; +} + +unittest +{ + assert(struct_stat.sizeof == 88); +} + +enum : int +{ + S_IFIFO = 0010000, + S_IFCHR = 0020000, + S_IFDIR = 0040000, + S_IFBLK = 0060000, + S_IFREG = 0100000, + S_IFLNK = 0120000, + S_IFSOCK = 0140000, + + S_IFMT = 0170000, + + S_IREAD = 0000400, + S_IWRITE = 0000200, + S_IEXEC = 0000100, +} + +extern (C) +{ + int access(char*, int); + int open(char*, int, ...); + int read(int, void*, int); + int write(int, void*, int); + int close(int); + int lseek(int, int, int); + int fstat(int, struct_stat*); + int lstat(char*, struct_stat*); + int stat(char*, struct_stat*); + int chdir(char*); + int mkdir(char*, int); + int rmdir(char*); + char* getcwd(char*, int); + int chmod(char*, mode_t); + int fork(); + int dup(int); + int dup2(int, int); + int pipe(int[2]); + pid_t wait(int*); + int waitpid(pid_t, int*, int); + + uint alarm(uint); + char* basename(char*); + //wint_t btowc(int); + int chown(char*, uid_t, gid_t); + int chroot(char*); + size_t confstr(int, char*, size_t); + int creat(char*, mode_t); + char* ctermid(char*); + int dirfd(DIR*); + char* dirname(char*); + int fattach(int, char*); + int fchmod(int, mode_t); + int fdatasync(int); + int ffs(int); + int fmtmsg(int, char*, int, char*, char*, char*); + int fpathconf(int, int); + int fseeko(FILE*, off_t, int); + off_t ftello(FILE*); + + extern char** environ; +} + +struct timeval +{ + int tv_sec; + int tv_usec; +} + +struct struct_timezone +{ + int tz_minuteswest; + int tz_dstime; +} + +struct tm +{ + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; + int tm_gmtoff; + int tm_zone; +} + +extern (C) +{ + int gettimeofday(timeval*, struct_timezone*); + __time_t time(__time_t*); + char* asctime(tm*); + char* ctime(__time_t*); + tm* gmtime(__time_t*); + tm* localtime(__time_t*); + __time_t mktime(tm*); + char* asctime_r(tm* t, char* buf); + char* ctime_r(__time_t* timep, char* buf); + tm* gmtime_r(__time_t* timep, tm* result); + tm* localtime_r(__time_t* timep, tm* result); +} + +/**************************************************************/ +// Memory mapping from and + +enum +{ + PROT_NONE = 0, + PROT_READ = 1, + PROT_WRITE = 2, + PROT_EXEC = 4, +} + +// Memory mapping sharing types + +enum +{ MAP_SHARED = 1, + MAP_PRIVATE = 2, + MAP_TYPE = 0x0F, + MAP_FIXED = 0x10, + MAP_FILE = 0, + MAP_ANONYMOUS = 0x20, + MAP_ANON = 0x20, + MAP_GROWSDOWN = 0x100, + MAP_DENYWRITE = 0x800, + MAP_EXECUTABLE = 0x1000, + MAP_LOCKED = 0x2000, + MAP_NORESERVE = 0x4000, + MAP_POPULATE = 0x8000, + MAP_NONBLOCK = 0x10000, +} + +// Values for msync() + +enum +{ MS_ASYNC = 1, + MS_INVALIDATE = 2, + MS_SYNC = 4, +} + +// Values for mlockall() + +enum +{ + MCL_CURRENT = 1, + MCL_FUTURE = 2, +} + +// Values for mremap() + +enum +{ + MREMAP_MAYMOVE = 1, +} + +// Values for madvise + +enum +{ MADV_NORMAL = 0, + MADV_RANDOM = 1, + MADV_SEQUENTIAL = 2, + MADV_WILLNEED = 3, + MADV_DONTNEED = 4, +} + +extern (C) +{ +void* mmap(void*, size_t, int, int, int, off_t); +const void* MAP_FAILED = cast(void*)-1; + +int munmap(void*, size_t); +int mprotect(void*, size_t, int); +int msync(void*, size_t, int); +int madvise(void*, size_t, int); +int mlock(void*, size_t); +int munlock(void*, size_t); +int mlockall(int); +int munlockall(); +void* mremap(void*, size_t, size_t, int); +int mincore(void*, size_t, ubyte*); +int remap_file_pages(void*, size_t, int, size_t, int); +int shm_open(char*, int, int); +int shm_unlink(char*); +} + +extern(C) +{ + + enum + { + DT_UNKNOWN = 0, + DT_FIFO = 1, + DT_CHR = 2, + DT_DIR = 4, + DT_BLK = 6, + DT_REG = 8, + DT_LNK = 10, + DT_SOCK = 12, + DT_WHT = 14, + } + + struct dirent + { + int d_ino; + off_t d_off; + ushort d_reclen; + ubyte d_type; + char[256] d_name; + } + + struct DIR + { + // Managed by OS. + } + + DIR* opendir(char* name); + int closedir(DIR* dir); + dirent* readdir(DIR* dir); + void rewinddir(DIR* dir); + off_t telldir(DIR* dir); + void seekdir(DIR* dir, off_t offset); +} + + +extern(C) +{ + private import std.intrinsic; + + + int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* errorfds, timeval* timeout); + int fcntl(int s, int f, ...); + + + enum + { + EINTR = 4, + EINPROGRESS = 115, + } + + + const uint FD_SETSIZE = 1024; + //const uint NFDBITS = 8 * int.sizeof; // DMD 0.110: 8 * (int).sizeof is not an expression + const int NFDBITS = 32; + + + struct fd_set + { + int[FD_SETSIZE / NFDBITS] fds_bits; + alias fds_bits __fds_bits; + } + + + int FDELT(int d) + { + return d / NFDBITS; + } + + + int FDMASK(int d) + { + return 1 << (d % NFDBITS); + } + + + // Removes. + void FD_CLR(int fd, fd_set* set) + { + btr(cast(uint*)&set.fds_bits.ptr[FDELT(fd)], cast(uint)(fd % NFDBITS)); + } + + + // Tests. + int FD_ISSET(int fd, fd_set* set) + { + return bt(cast(uint*)&set.fds_bits.ptr[FDELT(fd)], cast(uint)(fd % NFDBITS)); + } + + + // Adds. + void FD_SET(int fd, fd_set* set) + { + bts(cast(uint*)&set.fds_bits.ptr[FDELT(fd)], cast(uint)(fd % NFDBITS)); + } + + + // Resets to zero. + void FD_ZERO(fd_set* set) + { + set.fds_bits[] = 0; + } +} + +extern (C) +{ + /* From + * See http://www.opengroup.org/onlinepubs/007908799/xsh/dlsym.html + */ + + const int RTLD_NOW = 0x00002; // Correct for Red Hat 8 + + void* dlopen(char* file, int mode); + int dlclose(void* handle); + void* dlsym(void* handle, char* name); + char* dlerror(); +} + +extern (C) +{ + /* from + */ + + struct passwd + { + char *pw_name; + char *pw_passwd; + uid_t pw_uid; + gid_t pw_gid; + char *pw_gecos; + char *pw_dir; + char *pw_shell; + } + + const size_t _SIGSET_NWORDS = 1024 / (8 * uint.sizeof); + struct sigset_t + { + uint[_SIGSET_NWORDS] __val; + } + + int getpwnam_r(char*, passwd*, void*, size_t, passwd**); + passwd* getpwnam(char*); + passwd* getpwuid(uid_t); + int getpwuid_r(uid_t, passwd*, char*, size_t, passwd**); + int kill(pid_t, int); + int sem_close(sem_t*); + int sigemptyset(sigset_t*); + int sigfillset(sigset_t*); + int sigismember(sigset_t*, int); + int sigsuspend(sigset_t*); +} + +extern (C) +{ + /* from semaphore.h + */ + + struct sem_t + { + _pthread_fastlock __sem_lock; + int __sem_value; + void* __sem_waiting; + } + + int sem_init(sem_t*, int, uint); + int sem_wait(sem_t*); + int sem_trywait(sem_t*); + int sem_post(sem_t*); + int sem_getvalue(sem_t*, int*); + int sem_destroy(sem_t*); +} + +extern (C) +{ + /* from utime.h + */ + + struct utimbuf + { + __time_t actime; + __time_t modtime; + } + + int utime(char* filename, utimbuf* buf); +} diff -uNrp dmd-1.004/src/phobos/std/c/linux/pthread.d gdc-0.22/d/phobos/std/c/linux/pthread.d --- dmd-1.004/src/phobos/std/c/linux/pthread.d 2007-01-26 22:58:42.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/linux/pthread.d 1970-01-01 01:00:00.000000000 +0100 @@ -1,257 +0,0 @@ -/* Written by Walter Bright, Christopher E. Miller, and many others. - * www.digitalmars.com - * Placed into public domain. - */ - -module std.c.linux.pthread; - -extern (C) -{ - /* pthread declarations taken from pthread headers and - http://svn.dsource.org/projects/bindings/trunk/pthreads.d - */ - - /* from bits/types.h - */ - - typedef int __time_t; - - /* from time.h - */ - - struct timespec - { - __time_t tv_sec; /* seconds */ - int tv_nsec; /* nanosecs. */ - } - - /* from bits/pthreadtypes.h - */ - - alias uint pthread_t; - alias uint pthread_key_t; - alias int pthread_once_t; - alias int clockid_t; - alias int pthread_spinlock_t; // volatile - - struct _pthread_descr_struct - { - /* Not defined in the headers ??? - Just needed here to typedef - the _pthread_descr pointer - */ - } - - typedef _pthread_descr_struct* _pthread_descr; - - struct _pthread_fastlock - { - int __status; - int __spinlock; - } - - typedef long __pthread_cond_align_t; - - struct pthread_cond_t - { - _pthread_fastlock __c_lock; - _pthread_descr __c_waiting; - char[48 - - _pthread_fastlock.sizeof - - _pthread_descr.sizeof - - __pthread_cond_align_t.sizeof - ] __padding; - __pthread_cond_align_t __align; - } - - struct pthread_condattr_t - { - int __dummy; - } - - struct pthread_mutex_t - { - int __m_reserved; - int __m_count; - _pthread_descr __m_owner; - int __m_kind; - _pthread_fastlock __m_lock; - } - - struct pthread_mutexattr_t - { - int __mutexkind; - } - - /* from pthread.h - */ - - struct _pthread_cleanup_buffer - { - void function(void*) __routine; - void* __arg; - int __canceltype; - _pthread_cleanup_buffer* __prev; - } - - struct __sched_param // bits/sched.h - { - int __sched_priority; - } - - struct pthread_attr_t - { - int __detachstate; - int __schedpolicy; - __sched_param schedparam; - int __inheritshed; - int __scope; - size_t __guardsize; - int __stackaddr_set; - void* __stackaddr; - size_t __stacksize; - } - - struct pthread_barrier_t - { - _pthread_fastlock __ba_lock; - int __ba_required; - int __ba_present; - _pthread_descr __ba_waiting; - } - - struct pthread_barrierattr_t - { - int __pshared; - } - - struct pthread_rwlockattr_t - { - int __lockkind; - int __pshared; - } - - struct pthread_rwlock_t - { - _pthread_fastlock __rw_lock; - int __rw_readers; - _pthread_descr __rw_writer; - _pthread_descr __rw_read_waiting; - _pthread_descr __rw_write_waiting; - int __rw_kind; - int __rw_pshared; - } - - int pthread_mutex_init(pthread_mutex_t*, pthread_mutexattr_t*); - int pthread_mutex_destroy(pthread_mutex_t*); - int pthread_mutex_trylock(pthread_mutex_t*); - int pthread_mutex_lock(pthread_mutex_t*); - int pthread_mutex_unlock(pthread_mutex_t*); - - int pthread_mutexattr_init(pthread_mutexattr_t*); - int pthread_mutexattr_destroy(pthread_mutexattr_t*); - - int pthread_cond_init(pthread_cond_t*, pthread_condattr_t*); - int pthread_cond_destroy(pthread_cond_t*); - int pthread_cond_signal(pthread_cond_t*); - int pthread_cond_wait(pthread_cond_t*, pthread_mutex_t*); - int pthread_cond_timedwait(pthread_cond_t*, pthread_mutex_t*, timespec*); - - int pthread_attr_init(pthread_attr_t*); - int pthread_attr_destroy(pthread_attr_t*); - int pthread_attr_setdetachstate(pthread_attr_t*, int); - int pthread_attr_getdetachstate(pthread_attr_t*, int*); - int pthread_attr_setinheritsched(pthread_attr_t*, int); - int pthread_attr_getinheritsched(pthread_attr_t*, int*); - int pthread_attr_setschedparam(pthread_attr_t*, __sched_param*); - int pthread_attr_getschedparam(pthread_attr_t*, __sched_param*); - int pthread_attr_setschedpolicy(pthread_attr_t*, int); - int pthread_attr_getschedpolicy(pthread_attr_t*, int*); - int pthread_attr_setscope(pthread_attr_t*, int); - int pthread_attr_getscope(pthread_attr_t*, int*); - int pthread_attr_setguardsize(pthread_attr_t*, size_t); - int pthread_attr_getguardsize(pthread_attr_t*, size_t*); - int pthread_attr_setstack(pthread_attr_t*, void*, size_t); - int pthread_attr_getstack(pthread_attr_t*, void**, size_t*); - int pthread_attr_setstackaddr(pthread_attr_t*, void*); - int pthread_attr_getstackaddr(pthread_attr_t*, void**); - int pthread_attr_setstacksize(pthread_attr_t*, size_t); - int pthread_attr_getstacksize(pthread_attr_t*, size_t*); - - int pthread_barrierattr_init(pthread_barrierattr_t*); - int pthread_barrierattr_getpshared(pthread_barrierattr_t*, int*); - int pthread_barrierattr_destroy(pthread_barrierattr_t*); - int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int); - - int pthread_barrier_init(pthread_barrier_t*, pthread_barrierattr_t*, uint); - int pthread_barrier_destroy(pthread_barrier_t*); - int pthread_barrier_wait(pthread_barrier_t*); - - int pthread_condattr_init(pthread_condattr_t*); - int pthread_condattr_destroy(pthread_condattr_t*); - int pthread_condattr_getpshared(pthread_condattr_t*, int*); - int pthread_condattr_setpshared(pthread_condattr_t*, int); - - int pthread_detach(pthread_t); - void pthread_exit(void*); - int pthread_getattr_np(pthread_t, pthread_attr_t*); - int pthread_getconcurrency(); - int pthread_getcpuclockid(pthread_t, clockid_t*); - - int pthread_mutexattr_getpshared(pthread_mutexattr_t*, int*); - int pthread_mutexattr_setpshared(pthread_mutexattr_t*, int); - int pthread_mutexattr_settype(pthread_mutexattr_t*, int); - int pthread_mutexattr_gettype(pthread_mutexattr_t*, int*); - int pthread_mutex_timedlock(pthread_mutex_t*, timespec*); - int pthread_yield(); - - int pthread_rwlock_init(pthread_rwlock_t*, pthread_rwlockattr_t*); - int pthread_rwlock_destroy(pthread_rwlock_t*); - int pthread_rwlock_rdlock(pthread_rwlock_t*); - int pthread_rwlock_tryrdlock(pthread_rwlock_t*); - int pthread_rwlock_timedrdlock(pthread_rwlock_t*, timespec*); - int pthread_rwlock_wrlock(pthread_rwlock_t*); - int pthread_rwlock_trywrlock(pthread_rwlock_t*); - int pthread_rwlock_timedwrlock(pthread_rwlock_t*, timespec*); - int pthread_rwlock_unlock(pthread_rwlock_t*); - - int pthread_rwlockattr_init(pthread_rwlockattr_t*); - int pthread_rwlockattr_destroy(pthread_rwlockattr_t*); - int pthread_rwlockattr_getpshared(pthread_rwlockattr_t*, int*); - int pthread_rwlockattr_setpshared(pthread_rwlockattr_t*, int); - int pthread_rwlockattr_getkind_np(pthread_rwlockattr_t*, int*); - int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t*, int); - - int pthread_spin_init(pthread_spinlock_t*, int); - int pthread_spin_destroy(pthread_spinlock_t*); - int pthread_spin_lock(pthread_spinlock_t*); - int pthread_spin_trylock(pthread_spinlock_t*); - int pthread_spin_unlock(pthread_spinlock_t*); - - int pthread_cancel(pthread_t); - void pthread_testcancel(); - int pthread_once(pthread_once_t*, void function()); - - int pthread_join(pthread_t, void**); - int pthread_create(pthread_t*, pthread_attr_t*, void*function(void*), void*); - pthread_t pthread_self(); - int pthread_equal(pthread_t, pthread_t); - int pthread_atfork(void function(), void function(), void function()); - void pthread_kill_other_threads_np(); - int pthread_setschedparam(pthread_t, int, __sched_param*); - int pthread_getschedparam(pthread_t, int*, __sched_param*); - int pthread_cond_broadcast(pthread_cond_t*); - int pthread_key_create(pthread_key_t*, void function(void*)); - int pthread_key_delete(pthread_key_t); - int pthread_setconcurrency(int); - int pthread_setspecific(pthread_key_t, void*); - void* pthread_getspecific(pthread_key_t); - int pthread_setcanceltype(int, int*); - int pthread_setcancelstate(int, int*); - - void _pthread_cleanup_push(_pthread_cleanup_buffer*, void function(void*), void*); - void _pthread_cleanup_push_defer(_pthread_cleanup_buffer*, void function(void*), void*); - void _pthread_cleanup_pop(_pthread_cleanup_buffer*, int); - void _pthread_cleanup_pop_restore(_pthread_cleanup_buffer*, int); -} - diff -uNrp dmd-1.004/src/phobos/std/c/linux/pthread.d.orig-dmd gdc-0.22/d/phobos/std/c/linux/pthread.d.orig-dmd --- dmd-1.004/src/phobos/std/c/linux/pthread.d.orig-dmd 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/linux/pthread.d.orig-dmd 2007-01-27 17:44:01.000000000 +0100 @@ -0,0 +1,257 @@ +/* Written by Walter Bright, Christopher E. Miller, and many others. + * www.digitalmars.com + * Placed into public domain. + */ + +module std.c.linux.pthread; + +extern (C) +{ + /* pthread declarations taken from pthread headers and + http://svn.dsource.org/projects/bindings/trunk/pthreads.d + */ + + /* from bits/types.h + */ + + typedef int __time_t; + + /* from time.h + */ + + struct timespec + { + __time_t tv_sec; /* seconds */ + int tv_nsec; /* nanosecs. */ + } + + /* from bits/pthreadtypes.h + */ + + alias uint pthread_t; + alias uint pthread_key_t; + alias int pthread_once_t; + alias int clockid_t; + alias int pthread_spinlock_t; // volatile + + struct _pthread_descr_struct + { + /* Not defined in the headers ??? + Just needed here to typedef + the _pthread_descr pointer + */ + } + + typedef _pthread_descr_struct* _pthread_descr; + + struct _pthread_fastlock + { + int __status; + int __spinlock; + } + + typedef long __pthread_cond_align_t; + + struct pthread_cond_t + { + _pthread_fastlock __c_lock; + _pthread_descr __c_waiting; + char[48 + - _pthread_fastlock.sizeof + - _pthread_descr.sizeof + - __pthread_cond_align_t.sizeof + ] __padding; + __pthread_cond_align_t __align; + } + + struct pthread_condattr_t + { + int __dummy; + } + + struct pthread_mutex_t + { + int __m_reserved; + int __m_count; + _pthread_descr __m_owner; + int __m_kind; + _pthread_fastlock __m_lock; + } + + struct pthread_mutexattr_t + { + int __mutexkind; + } + + /* from pthread.h + */ + + struct _pthread_cleanup_buffer + { + void function(void*) __routine; + void* __arg; + int __canceltype; + _pthread_cleanup_buffer* __prev; + } + + struct __sched_param // bits/sched.h + { + int __sched_priority; + } + + struct pthread_attr_t + { + int __detachstate; + int __schedpolicy; + __sched_param schedparam; + int __inheritshed; + int __scope; + size_t __guardsize; + int __stackaddr_set; + void* __stackaddr; + size_t __stacksize; + } + + struct pthread_barrier_t + { + _pthread_fastlock __ba_lock; + int __ba_required; + int __ba_present; + _pthread_descr __ba_waiting; + } + + struct pthread_barrierattr_t + { + int __pshared; + } + + struct pthread_rwlockattr_t + { + int __lockkind; + int __pshared; + } + + struct pthread_rwlock_t + { + _pthread_fastlock __rw_lock; + int __rw_readers; + _pthread_descr __rw_writer; + _pthread_descr __rw_read_waiting; + _pthread_descr __rw_write_waiting; + int __rw_kind; + int __rw_pshared; + } + + int pthread_mutex_init(pthread_mutex_t*, pthread_mutexattr_t*); + int pthread_mutex_destroy(pthread_mutex_t*); + int pthread_mutex_trylock(pthread_mutex_t*); + int pthread_mutex_lock(pthread_mutex_t*); + int pthread_mutex_unlock(pthread_mutex_t*); + + int pthread_mutexattr_init(pthread_mutexattr_t*); + int pthread_mutexattr_destroy(pthread_mutexattr_t*); + + int pthread_cond_init(pthread_cond_t*, pthread_condattr_t*); + int pthread_cond_destroy(pthread_cond_t*); + int pthread_cond_signal(pthread_cond_t*); + int pthread_cond_wait(pthread_cond_t*, pthread_mutex_t*); + int pthread_cond_timedwait(pthread_cond_t*, pthread_mutex_t*, timespec*); + + int pthread_attr_init(pthread_attr_t*); + int pthread_attr_destroy(pthread_attr_t*); + int pthread_attr_setdetachstate(pthread_attr_t*, int); + int pthread_attr_getdetachstate(pthread_attr_t*, int*); + int pthread_attr_setinheritsched(pthread_attr_t*, int); + int pthread_attr_getinheritsched(pthread_attr_t*, int*); + int pthread_attr_setschedparam(pthread_attr_t*, __sched_param*); + int pthread_attr_getschedparam(pthread_attr_t*, __sched_param*); + int pthread_attr_setschedpolicy(pthread_attr_t*, int); + int pthread_attr_getschedpolicy(pthread_attr_t*, int*); + int pthread_attr_setscope(pthread_attr_t*, int); + int pthread_attr_getscope(pthread_attr_t*, int*); + int pthread_attr_setguardsize(pthread_attr_t*, size_t); + int pthread_attr_getguardsize(pthread_attr_t*, size_t*); + int pthread_attr_setstack(pthread_attr_t*, void*, size_t); + int pthread_attr_getstack(pthread_attr_t*, void**, size_t*); + int pthread_attr_setstackaddr(pthread_attr_t*, void*); + int pthread_attr_getstackaddr(pthread_attr_t*, void**); + int pthread_attr_setstacksize(pthread_attr_t*, size_t); + int pthread_attr_getstacksize(pthread_attr_t*, size_t*); + + int pthread_barrierattr_init(pthread_barrierattr_t*); + int pthread_barrierattr_getpshared(pthread_barrierattr_t*, int*); + int pthread_barrierattr_destroy(pthread_barrierattr_t*); + int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int); + + int pthread_barrier_init(pthread_barrier_t*, pthread_barrierattr_t*, uint); + int pthread_barrier_destroy(pthread_barrier_t*); + int pthread_barrier_wait(pthread_barrier_t*); + + int pthread_condattr_init(pthread_condattr_t*); + int pthread_condattr_destroy(pthread_condattr_t*); + int pthread_condattr_getpshared(pthread_condattr_t*, int*); + int pthread_condattr_setpshared(pthread_condattr_t*, int); + + int pthread_detach(pthread_t); + void pthread_exit(void*); + int pthread_getattr_np(pthread_t, pthread_attr_t*); + int pthread_getconcurrency(); + int pthread_getcpuclockid(pthread_t, clockid_t*); + + int pthread_mutexattr_getpshared(pthread_mutexattr_t*, int*); + int pthread_mutexattr_setpshared(pthread_mutexattr_t*, int); + int pthread_mutexattr_settype(pthread_mutexattr_t*, int); + int pthread_mutexattr_gettype(pthread_mutexattr_t*, int*); + int pthread_mutex_timedlock(pthread_mutex_t*, timespec*); + int pthread_yield(); + + int pthread_rwlock_init(pthread_rwlock_t*, pthread_rwlockattr_t*); + int pthread_rwlock_destroy(pthread_rwlock_t*); + int pthread_rwlock_rdlock(pthread_rwlock_t*); + int pthread_rwlock_tryrdlock(pthread_rwlock_t*); + int pthread_rwlock_timedrdlock(pthread_rwlock_t*, timespec*); + int pthread_rwlock_wrlock(pthread_rwlock_t*); + int pthread_rwlock_trywrlock(pthread_rwlock_t*); + int pthread_rwlock_timedwrlock(pthread_rwlock_t*, timespec*); + int pthread_rwlock_unlock(pthread_rwlock_t*); + + int pthread_rwlockattr_init(pthread_rwlockattr_t*); + int pthread_rwlockattr_destroy(pthread_rwlockattr_t*); + int pthread_rwlockattr_getpshared(pthread_rwlockattr_t*, int*); + int pthread_rwlockattr_setpshared(pthread_rwlockattr_t*, int); + int pthread_rwlockattr_getkind_np(pthread_rwlockattr_t*, int*); + int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t*, int); + + int pthread_spin_init(pthread_spinlock_t*, int); + int pthread_spin_destroy(pthread_spinlock_t*); + int pthread_spin_lock(pthread_spinlock_t*); + int pthread_spin_trylock(pthread_spinlock_t*); + int pthread_spin_unlock(pthread_spinlock_t*); + + int pthread_cancel(pthread_t); + void pthread_testcancel(); + int pthread_once(pthread_once_t*, void function()); + + int pthread_join(pthread_t, void**); + int pthread_create(pthread_t*, pthread_attr_t*, void*function(void*), void*); + pthread_t pthread_self(); + int pthread_equal(pthread_t, pthread_t); + int pthread_atfork(void function(), void function(), void function()); + void pthread_kill_other_threads_np(); + int pthread_setschedparam(pthread_t, int, __sched_param*); + int pthread_getschedparam(pthread_t, int*, __sched_param*); + int pthread_cond_broadcast(pthread_cond_t*); + int pthread_key_create(pthread_key_t*, void function(void*)); + int pthread_key_delete(pthread_key_t); + int pthread_setconcurrency(int); + int pthread_setspecific(pthread_key_t, void*); + void* pthread_getspecific(pthread_key_t); + int pthread_setcanceltype(int, int*); + int pthread_setcancelstate(int, int*); + + void _pthread_cleanup_push(_pthread_cleanup_buffer*, void function(void*), void*); + void _pthread_cleanup_push_defer(_pthread_cleanup_buffer*, void function(void*), void*); + void _pthread_cleanup_pop(_pthread_cleanup_buffer*, int); + void _pthread_cleanup_pop_restore(_pthread_cleanup_buffer*, int); +} + diff -uNrp dmd-1.004/src/phobos/std/c/linux/socket.d gdc-0.22/d/phobos/std/c/linux/socket.d --- dmd-1.004/src/phobos/std/c/linux/socket.d 2007-01-26 22:58:42.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/linux/socket.d 2006-12-17 06:03:04.000000000 +0100 @@ -35,20 +35,19 @@ int setsockopt(int s, int level, int opt uint inet_addr(char* cp); char* inet_ntoa(in_addr ina); hostent* gethostbyname(char* name); -int gethostbyname_r(char* name, hostent* ret, void* buf, size_t buflen, hostent** result, int* h_errnop); -int gethostbyname2_r(char* name, int af, hostent* ret, void* buf, size_t buflen, hostent** result, int* h_errnop); hostent* gethostbyaddr(void* addr, int len, int type); protoent* getprotobyname(char* name); protoent* getprotobynumber(int number); servent* getservbyname(char* name, char* proto); servent* getservbyport(int port, char* proto); int gethostname(char* name, int namelen); +int gethostbyname_r(char* name, hostent* ret, void* buf, size_t buflen, hostent** result, int* h_errnop); +int gethostbyname2_r(char* name, int af, hostent* ret, void* buf, size_t buflen, hostent** result, int* h_errnop); int getaddrinfo(char* nodename, char* servname, addrinfo* hints, addrinfo** res); void freeaddrinfo(addrinfo* ai); int getnameinfo(sockaddr* sa, socklen_t salen, char* node, socklen_t nodelen, char* service, socklen_t servicelen, int flags); - enum: int { AF_UNSPEC = 0, diff -uNrp dmd-1.004/src/phobos/std/c/mach/mach.d gdc-0.22/d/phobos/std/c/mach/mach.d --- dmd-1.004/src/phobos/std/c/mach/mach.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/mach/mach.d 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,61 @@ +/* GDC -- D front-end for GCC + Copyright (C) 2004 David Friedman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +module std.c.mach.mach; + +private import gcc.builtins; + +private alias __builtin_abi_uint natural_t; + +private import std.c.mach.mach_extern; + +extern(C): + +enum { + SYNC_POLICY_FIFO = 0x0, + SYNC_POLICY_FIXED_PRIORITY = 0x1, + SYNC_POLICY_REVERSED = 0x2, + SYNC_POLICY_ORDER_MASK = 0x3, + SYNC_POLICY_LIFO = (SYNC_POLICY_FIFO|SYNC_POLICY_REVERSED) +} + +enum { + KERN_SUCCESS = 0 +} + +alias natural_t semaphore_t; // TODO: natural_t +alias natural_t task_t; // TODO: natural_t +alias natural_t mach_port_t; // TODO: natural_t +alias int kern_return_t; +kern_return_t semaphore_create +( + task_t task, + semaphore_t *semaphore, + int policy, + int value +); +kern_return_t semaphore_destroy +( + task_t task, + semaphore_t semaphore +); +kern_return_t semaphore_signal (semaphore_t semaphore); +kern_return_t semaphore_wait (semaphore_t semaphore); + +// just in case this actually gets defined.. +extern(D) mach_port_t current_task() { return mach_task_self_; } diff -uNrp dmd-1.004/src/phobos/std/c/mach/mach_extern.d gdc-0.22/d/phobos/std/c/mach/mach_extern.d --- dmd-1.004/src/phobos/std/c/mach/mach_extern.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/mach/mach_extern.d 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,24 @@ +/* GDC -- D front-end for GCC + Copyright (C) 2004 David Friedman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +module std.c.mach.mach_extern; + +private import std.c.mach.mach; + +// This probably isn't stable +extern (C) mach_port_t mach_task_self_; diff -uNrp dmd-1.004/src/phobos/std/c/math.d gdc-0.22/d/phobos/std/c/math.d --- dmd-1.004/src/phobos/std/c/math.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/math.d 2006-06-02 05:31:29.000000000 +0200 @@ -7,6 +7,12 @@ * WIKI=Phobos/StdCMath */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2005 +*/ + module std.c.math; extern (C): @@ -48,6 +54,241 @@ const int MATH_ERRNO = 1; /// const int MATH_ERREXCEPT = 2; /// const int math_errhandling = MATH_ERRNO | MATH_ERREXCEPT; /// +version (GNU) +{ + private import gcc.builtins; + + double acos(double x); + float acosf(float x); + + double asin(double x); + float asinf(float x); + + double atan(double x); + float atanf(float x); + + double atan2(double y, double x); + float atan2f(float y, float x); + + double cos(double x); + float cosf(float x); + + double sin(double x); + float sinf(float x); + + double tan(double x); + float tanf(float x); + + double acosh(double x); + float acoshf(float x); + + double asinh(double x); + float asinhf(float x); + + double atanh(double x); + float atanhf(float x); + + double cosh(double x); + float coshf(float x); + + double sinh(double x); + float sinhf(float x); + + double tanh(double x); + float tanhf(float x); + + double exp(double x); + float expf(float x); + + double exp2(double x); + float exp2f(float x); + + double expm1(double x); + float expm1f(float x); + + double frexp(double value, int *exp); + float frexpf(float value, int *exp); + + int ilogb(double x); + int ilogbf(float x); + + double ldexp(double x, int exp); + float ldexpf(float x, int exp); + + double log(double x); + float logf(float x); + + double log10(double x); + float log10f(float x); + + double log1p(double x); + float log1pf(float x); + + double log2(double x); + float log2f(float x); + + double logb(double x); + float logbf(float x); + + double modf(double value, double *iptr); + float modff(float value, float *iptr); + + double scalbn(double x, int n); + float scalbnf(float x, int n); + + double scalbln(double x, int n); + float scalblnf(float x, int n); + + double cbrt(double x); + float cbrtf(float x); + + double fabs(double x); + float fabsf(float x); + + double hypot(double x, double y); + float hypotf(float x, float y); + + double pow(double x, double y); + float powf(float x, float y); + + double sqrt(double x); + float sqrtf(float x); + + double erf(double x); + float erff(float x); + + double erfc(double x); + float erfcf(float x); + + double lgamma(double x); + float lgammaf(float x); + + double tgamma(double x); + float tgammaf(float x); + + double ceil(double x); + float ceilf(float x); + + double floor(double x); + float floorf(float x); + + double nearbyint(double x); + float nearbyintf(float x); + + double rint(double x); + float rintf(float x); + + int lrint(double x); + int lrintf(float x); + + long llrint(double x); + long llrintf(float x); + + double round(double x); + float roundf(float x); + + int lround(double x); + int lroundf(float x); + + long llround(double x); + long llroundf(float x); + + double trunc(double x); + float truncf(float x); + + double fmod(double x, double y); + float fmodf(float x, float y); + + double remainder(double x, double y); + float remainderf(float x, float y); + + double remquo(double x, double y, int *quo); + float remquof(float x, float y, int *quo); + + double copysign(double x, double y); + float copysignf(float x, float y); + + double nan(char *tagp); + float nanf(char *tagp); + + double nextafter(double x, double y); + float nextafterf(float x, float y); + + double nexttoward(double x, real y); + float nexttowardf(float x, real y); + + double fdim(double x, double y); + float fdimf(float x, float y); + + double fmax(double x, double y); + float fmaxf(float x, float y); + + double fmin(double x, double y); + float fminf(float x, float y); + + double fma(double x, double y, double z); + float fmaf(float x, float y, float z); + + private import gcc.config; + // unfortunately, these do not always exist in a library + alias gcc.config.acosl acosl; + alias gcc.config.asinl asinl; + alias gcc.config.atanl atanl; + alias gcc.config.atan2l atan2l; + alias gcc.config.cosl cosl; + alias gcc.config.sinl sinl; + alias gcc.config.tanl tanl; + alias gcc.config.acoshl acoshl; + alias gcc.config.asinhl asinhl; + alias gcc.config.atanhl atanhl; + alias gcc.config.coshl coshl; + alias gcc.config.sinhl sinhl; + alias gcc.config.tanhl tanhl; + alias gcc.config.expl expl; + alias gcc.config.exp2l exp2l; + alias gcc.config.expm1l expm1l; + alias gcc.config.frexpl frexpl; + alias gcc.config.ilogbl ilogbl; + alias gcc.config.ldexpl ldexpl; + alias gcc.config.logl logl; + alias gcc.config.log10l log10l; + alias gcc.config.log1pl log1pl; + alias gcc.config.log2l log2l; + alias gcc.config.logbl logbl; + alias gcc.config.modfl modfl; + alias gcc.config.scalbnl scalbnl; + alias gcc.config.scalblnl scalblnl; + alias gcc.config.cbrtl cbrtl; + alias gcc.config.fabsl fabsl; + alias gcc.config.hypotl hypotl; + alias gcc.config.powl powl; + alias gcc.config.sqrtl sqrtl; + alias gcc.config.erfl erfl; + alias gcc.config.erfcl erfcl; + alias gcc.config.lgammal lgammal; + alias gcc.config.tgammal tgammal; + alias gcc.config.ceill ceill; + alias gcc.config.floorl floorl; + alias gcc.config.nearbyintl nearbyintl; + alias gcc.config.rintl rintl; + alias gcc.config.lrintl lrintl; + alias gcc.config.llrintl llrintl; + alias gcc.config.roundl roundl; + alias gcc.config.lroundl lroundl; + alias gcc.config.llroundl llroundl; + alias gcc.config.truncl truncl; + alias gcc.config.fmodl fmodl; + alias gcc.config.remainderl remainderl; + alias gcc.config.remquol remquol; + alias gcc.config.copysignl copysignl; + alias gcc.config.nanl nanl;//doesn't work... + alias gcc.config.nextafterl nextafterl; + alias gcc.config.nexttowardl nexttowardl; + alias gcc.config.fdiml fdiml; + alias gcc.config.fmaxl fmaxl; + alias gcc.config.fminl fminl; + alias gcc.config.fmal fmal; +} else { double acos(double x); /// float acosf(float x); /// ditto real acosl(real x); /// ditto @@ -275,6 +516,7 @@ real fminl(real x, real y); /// ditto double fma(double x, double y, double z); /// float fmaf(float x, float y, float z); /// ditto real fmal(real x, real y, real z); /// ditto +} /// int isgreater(real x, real y) { return !(x !> y); } diff -uNrp dmd-1.004/src/phobos/std/c/skyos/compat.d gdc-0.22/d/phobos/std/c/skyos/compat.d --- dmd-1.004/src/phobos/std/c/skyos/compat.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/skyos/compat.d 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,39 @@ +module std.c.skyos.compat; +private import std.c.unix.unix; +private import std.c.skyos.skyos; + +enum { + TASK_CREATE_FLAG_WANT_WAIT_FOR = 0x00002000 +} + +// libpthread pthread_create has problems? +int pthread_create(pthread_t * pth, pthread_attr_t * attr, void* fn, void * arg) +{ + int tid = ThreadCreate("thread", TASK_CREATE_FLAG_WANT_WAIT_FOR, + cast(void *) fn, cast(uint) arg, 0, 0, 0, 0, 0, 0, 0, 0, 0); + if (tid) { + *pth = tid; + return 0; + } else { + return EAGAIN; + } +} +int pthread_join(pthread_t thread, void ** result) +{ + int v; + int r = ThreadWait(thread, & v); + if (r == thread) { + if (result) + *result = null; + return 0; + } else + return -1; +} + +pthread_t pthread_self() { return cast(pthread_t) ThreadGetPid(); } +int pthread_equal(pthread_t a, pthread_t b) { return a == b; } +int pthread_kill(pthread_t pth, int sig) { return kill(cast(pid_t) pth, sig); } +alias ThreadYield sched_yield; + +int pthread_suspend_np(pthread_t p) { return ThreadSuspend(p) == 0 ? 0 : -1; } +int pthread_continue_np(pthread_t p) { return ThreadResume(p) == 0 ? 0 : -1; } diff -uNrp dmd-1.004/src/phobos/std/c/skyos/skyos.d gdc-0.22/d/phobos/std/c/skyos/skyos.d --- dmd-1.004/src/phobos/std/c/skyos/skyos.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/skyos/skyos.d 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,11 @@ +module std.c.skyos.skyos; + +extern(C): + +int ThreadCreate (char *ucName, uint uiFlags, void *fpFunction, uint arg1, uint arg2, uint arg3, uint arg4, uint arg5, uint arg6, uint arg7, uint arg8, uint arg9, uint arg10); +int ThreadWait (int iPid, int *iStatus); +int ThreadGetPid (); +int ThreadSuspend (int iPid); +int ThreadResume (int iPid); +void ThreadYield (); +int ThreadSleep (uint uiMilliseconds); diff -uNrp dmd-1.004/src/phobos/std/c/stdarg.d gdc-0.22/d/phobos/std/c/stdarg.d --- dmd-1.004/src/phobos/std/c/stdarg.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/stdarg.d 2006-06-02 05:31:29.000000000 +0200 @@ -9,15 +9,49 @@ /* This is for use with extern(C) variable argument lists. */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + module std.c.stdarg; +version (GNU) { + private import gcc.builtins; + alias __builtin_va_list va_list; + alias __builtin_va_end va_end; + alias __builtin_va_copy va_copy; + + // The va_start and va_arg template functions are magically + // handled by the compiler. +} else { + alias void* va_list; +void va_end(va_list ap) +{ + +} + +void va_copy(out va_list dest, va_list src) +{ + static if ( is( dest T == T[1]) ) { + dest[0] = src[0]; + } else { + dest = src; + } +} + +} + template va_start(T) { void va_start(out va_list ap, inout T parmn) { + /* ap = cast(va_list)(cast(void*)&parmn + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1))); + */ } } @@ -25,18 +59,13 @@ template va_arg(T) { T va_arg(inout va_list ap) { + /* T arg = *cast(T*)ap; ap = cast(va_list)(cast(void*)ap + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1))); return arg; + */ + T t; + return t; } } -void va_end(va_list ap) -{ - -} - -void va_copy(out va_list dest, va_list src) -{ - dest = src; -} diff -uNrp dmd-1.004/src/phobos/std/c/stddef.d gdc-0.22/d/phobos/std/c/stddef.d --- dmd-1.004/src/phobos/std/c/stddef.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/stddef.d 2006-06-02 05:31:29.000000000 +0200 @@ -1,10 +1,10 @@ /** - * C's <stddef.h> - * Authors: Walter Bright, Digital Mars, www.digitalmars.com + * C's <stdarg.h> + * Authors: Hauke Duden and Walter Bright, Digital Mars, www.digitalmars.com * License: Public Domain * Macros: - * WIKI=Phobos/StdCStddef + * WIKI=Phobos/StdCStdarg */ module std.c.stddef; @@ -17,6 +17,10 @@ else version (linux) { alias dchar wchar_t; } +else version (Unix) +{ + alias dchar wchar_t; +} else { static assert(0); diff -uNrp dmd-1.004/src/phobos/std/c/stdio.d gdc-0.22/d/phobos/std/c/stdio.d --- dmd-1.004/src/phobos/std/c/stdio.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/stdio.d 2006-06-02 05:31:29.000000000 +0200 @@ -7,6 +7,12 @@ * WIKI=Phobos/StdCStdio */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + module std.c.stdio; @@ -16,7 +22,18 @@ private import std.c.stdarg; extern (C): -version (Win32) +version (GNU) +{ + private import gcc.builtins; + private import gcc.config; + alias gcc.config.EOF EOF; + alias gcc.config.FOPEN_MAX FOPEN_MAX; + alias gcc.config.FILENAME_MAX FILENAME_MAX; + alias gcc.config.PATH_MAX PATH_MAX; + alias gcc.config.TMP_MAX TMP_MAX; + alias gcc.config.L_tmpnam L_tmpnam; +} +else version (Win32) { const int _NFILE = 60; /// const int BUFSIZ = 0x4000; /// @@ -28,8 +45,7 @@ version (Win32) const int SYS_OPEN = _SYS_OPEN; /// const wchar WEOF = 0xFFFF; /// } - -version (linux) +else version (linux) { const int EOF = -1; const int FOPEN_MAX = 16; @@ -54,7 +70,7 @@ struct _iobuf int _bufsiz; int __tmpnum; } - version (linux) + else version (linux) { char* _read_ptr; char* _read_end; @@ -77,6 +93,10 @@ struct _iobuf char[1] _shortbuf; void* _lock; } + else version (GNU) { + byte[gcc.config.FILE_struct_size] opaque; + } + } alias _iobuf FILE; /// @@ -98,8 +118,13 @@ enum version (Win32) { - extern FILE _iob[_NFILE]; - extern void function() _fcloseallp; + version (GNU) { + // _NFILE is not defined anywhere + extern export FILE _iob[5]; + } else { + extern FILE _iob[_NFILE]; + extern void function() _fcloseallp; + } } version (Win32) @@ -131,16 +156,59 @@ version (linux) } } -version (Win32) + +version (GNU_CBridge_Stdio) { + extern FILE * _d_gnu_cbridge_stdin; + extern FILE * _d_gnu_cbridge_stdout; + extern FILE * _d_gnu_cbridge_stderr; + + /* Call from dgccmain2. Can't use a static constructor here + because std.c.stdio is not compiled. */ + extern void _d_gnu_cbridge_init_stdio(); + + alias _d_gnu_cbridge_stdin stdin; + alias _d_gnu_cbridge_stdout stdout; + alias _d_gnu_cbridge_stderr stderr; +} +else version (Win32) +{ + // This works for DMD/DMC and MinGW/msvcrt const FILE *stdin = &_iob[0]; /// const FILE *stdout = &_iob[1]; /// const FILE *stderr = &_iob[2]; /// const FILE *stdaux = &_iob[3]; /// const FILE *stdprn = &_iob[4]; /// } - -version (linux) +else version (aix) +{ + // 32- and 64-bit + extern FILE _iob[16]; + const FILE *stdin = &_iob[0]; + const FILE *stdout = &_iob[1]; + const FILE *stderr = &_iob[2]; +} +else version (darwin) +{ + version (GNU_BitsPerPointer32) + { + static assert(gcc.config.FILE_struct_size != 0); + extern FILE __sF[3]; + const FILE * stdin = &__sF[0]; + const FILE * stdout = &__sF[1]; + const FILE * stderr = &__sF[2]; + } + else version (GNU_BitsPerPointer64) + { + extern FILE *__stdinp; + extern FILE *__stdoutp; + extern FILE *__stderrp; + alias __stdinp stdin; + alias __stdoutp stdout; + alias __stderrp stderr; + } +} +else version (linux) { extern FILE *stdin; extern FILE *stdout; @@ -151,7 +219,11 @@ version (Win32) { const char[] _P_tmpdir = "\\"; const wchar[] _wP_tmpdir = "\\"; - const int L_tmpnam = _P_tmpdir.length + 12; + version (GNU) { } + else + { + const int L_tmpnam = _P_tmpdir.length + 12; + } } alias int fpos_t; /// @@ -208,6 +280,10 @@ int getc(FILE *fp) { return fgetc(fp); /// int putc(int c,FILE *fp) { return fputc(c,fp); } +version(PPC) + version(Linux) + version=PPCLinux; + version (Win32) { /// @@ -224,8 +300,74 @@ version (Win32) int _snprintf(char *,size_t,char *,...); int _vsnprintf(char *,size_t,char *,va_list); } - -version (linux) +else version (darwin) +{ + private import std.c.darwin.ldblcompat; + + alias gcc.config.ferror ferror; + alias gcc.config.feof feof; + alias gcc.config.clearerr clearerr; + alias gcc.config.rewind rewind; + alias gcc.config._bufsize _bufsize; + alias gcc.config.fileno fileno; + + int snprintf(char *, size_t, char *, ...); + int vsnprintf(char *, size_t, char *, va_list); + + // printf is declared in object, but it won't be fixed unless std.c.stdio is imported... + pragma(GNU_asm,printf,"printf" ~ __DARWIN_LDBL_COMPAT); + pragma(GNU_asm,fprintf,"fprintf" ~ __DARWIN_LDBL_COMPAT); + pragma(GNU_asm,vfprintf,"vfprintf" ~ __DARWIN_LDBL_COMPAT); + pragma(GNU_asm,vprintf,"vprintf" ~ __DARWIN_LDBL_COMPAT); + pragma(GNU_asm,sprintf,"sprintf" ~ __DARWIN_LDBL_COMPAT); + pragma(GNU_asm,vsprintf,"vsprintf" ~ __DARWIN_LDBL_COMPAT); + pragma(GNU_asm,scanf,"scanf" ~ __DARWIN_LDBL_COMPAT); + pragma(GNU_asm,fscanf,"fscanf" ~ __DARWIN_LDBL_COMPAT); + pragma(GNU_asm,sscanf,"sscanf" ~ __DARWIN_LDBL_COMPAT); + pragma(GNU_asm,snprintf,"snprintf" ~ __DARWIN_LDBL_COMPAT); + pragma(GNU_asm,vsnprintf,"vsnprintf" ~ __DARWIN_LDBL_COMPAT); +} +else version (PPCLinux) +{ + private import std.c.linux.ldblcompat; + + alias gcc.config.ferror ferror; + alias gcc.config.feof feof; + alias gcc.config.clearerr clearerr; + alias gcc.config.rewind rewind; + alias gcc.config._bufsize _bufsize; + alias gcc.config.fileno fileno; + + int snprintf(char *, size_t, char *, ...); + int vsnprintf(char *, size_t, char *, va_list); + + // printf is declared in object, but it won't be fixed unless std.c.stdio is imported... + pragma(GNU_asm,printf,__LDBL_COMPAT_PFX ~ "printf"); + pragma(GNU_asm,fprintf,__LDBL_COMPAT_PFX ~ "fprintf"); + pragma(GNU_asm,vfprintf,__LDBL_COMPAT_PFX ~ "vfprintf"); + pragma(GNU_asm,vprintf,__LDBL_COMPAT_PFX ~ "vprintf"); + pragma(GNU_asm,sprintf,__LDBL_COMPAT_PFX ~ "sprintf"); + pragma(GNU_asm,vsprintf,__LDBL_COMPAT_PFX ~ "vsprintf"); + pragma(GNU_asm,scanf,__LDBL_COMPAT_PFX ~ "scanf"); + pragma(GNU_asm,fscanf,__LDBL_COMPAT_PFX ~ "fscanf"); + pragma(GNU_asm,sscanf,__LDBL_COMPAT_PFX ~ "sscanf"); + pragma(GNU_asm,snprintf,__LDBL_COMPAT_PFX ~ "snprintf"); + pragma(GNU_asm,vsnprintf,__LDBL_COMPAT_PFX ~ "vsnprintf"); +} +else version (GNU) +{ + alias gcc.config.ferror ferror; + alias gcc.config.feof feof; + alias gcc.config.clearerr clearerr; + alias gcc.config.rewind rewind; + alias gcc.config._bufsize _bufsize; + alias gcc.config.fileno fileno; + alias gcc.config.Csnprintf snprintf; + alias gcc.config.Cvsnprintf vsnprintf; + alias gcc.config.Csnprintf _snprintf; + alias gcc.config.Cvsnprintf _vsnprintf; +} +else version (linux) { int ferror(FILE *fp); int feof(FILE *fp); diff -uNrp dmd-1.004/src/phobos/std/c/stdlib.d gdc-0.22/d/phobos/std/c/stdlib.d --- dmd-1.004/src/phobos/std/c/stdlib.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/stdlib.d 2007-01-27 17:44:01.000000000 +0100 @@ -7,6 +7,12 @@ */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + module std.c.stdlib; private import std.c.stddef; @@ -42,22 +48,34 @@ struct lldiv_t { long quot,rem; } int system(char *); - void *alloca(uint); /// - - void *calloc(size_t, size_t); /// - void *malloc(size_t); /// ditto - void *realloc(void *, size_t); /// ditto + version (GNU) + { + private import gcc.builtins; + alias gcc.builtins.__builtin_alloca alloca; /// + } else { + void *alloca(uint); /// + } + + void *calloc(uint, uint); /// + void *malloc(uint); /// ditto + void *realloc(void *, uint); /// ditto void free(void *); /// ditto void *bsearch(void *,void *,size_t,size_t, int function(void *,void *)); /// - void qsort(void *base, size_t nelems, size_t elemsize, + void qsort(void *base, uint nelems, uint elemsize, int (*compare)(void *elem1, void *elem2)); /// ditto char* getenv(char*); /// int setenv(char*, char*, int); /// ditto void unsetenv(char*); /// ditto + version (GNU) + { + private import gcc.config; + alias gcc.config.RAND_MAX RAND_MAX; + } + int rand(); /// void srand(uint); /// ditto int random(int num); /// ditto @@ -73,15 +91,42 @@ int atoi(char *); /// ditto int atol(char *); /// ditto float strtof(char *,char **); /// ditto double strtod(char *,char **); /// ditto -real strtold(char *,char **); /// ditto + +//real strtold(char *,char **); +version (darwin) + version (GNU_Have_strtold) + version = darwin_strtold; +version(PPC) + version(Linux) + version=PPCLinux; +version (darwin_strtold) +{ + private import std.c.darwin.ldblcompat; + real strtold(char *, char **); /// ditto + pragma(GNU_asm,strtold,"strtold"~__DARWIN_LDBL_COMPAT); +} +else version (PPCLinux) +{ + private import std.c.linux.ldblcompat; + static if (std.c.linux.ldblcompat.__No_Long_Double_Math) + alias strtod strtold; /// ditto + else + alias gcc.config.cstrtold strtold; /// ditto +} +else +{ + private import gcc.config; + alias gcc.config.cstrtold strtold; /// ditto +} + long strtol(char *,char **,int); /// ditto uint strtoul(char *,char **,int); /// ditto long atoll(char *); /// ditto long strtoll(char *,char **,int); /// ditto ulong strtoull(char *,char **,int); /// ditto -char* itoa(int, char*, int); /// -char* ultoa(uint, char*, int); /// ditto +char* itoa(int, char*, int); +char* ultoa(uint, char*, int); int mblen(char *s, size_t n); /// int mbtowc(wchar_t *pwc, char *s, size_t n); /// ditto diff -uNrp dmd-1.004/src/phobos/std/c/string.d gdc-0.22/d/phobos/std/c/string.d --- dmd-1.004/src/phobos/std/c/string.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/string.d 2006-06-02 05:31:29.000000000 +0200 @@ -7,32 +7,62 @@ * WIKI=Phobos/StdCString */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, May 2006 +*/ + + module std.c.string; extern (C): +version (GNU) +{ + private import gcc.builtins; + alias __builtin_memcpy memcpy; /// + alias __builtin_strcpy strcpy; /// + alias __builtin_strncpy strncpy; /// + alias __builtin_strncat strncat; /// + alias __builtin_strncmp strncmp; /// + alias __builtin_strchr strchr; /// + alias __builtin_strcspn strcspn; /// + alias __builtin_strpbrk strpbrk; /// + alias __builtin_strrchr strrchr; /// + alias __builtin_strspn strspn; /// + alias __builtin_strstr strstr; /// + alias __builtin_memset memset; /// + alias __builtin_strlen strlen; /// + alias __builtin_strcmp strcmp; /// + alias __builtin_strcat strcat; /// + alias __builtin_memcmp memcmp; /// +} +else +{ void* memcpy(void* s1, void* s2, size_t n); /// -void* memmove(void* s1, void* s2, size_t n); /// char* strcpy(char* s1, char* s2); /// char* strncpy(char* s1, char* s2, size_t n); /// char* strncat(char* s1, char* s2, size_t n); /// -int strcoll(char* s1, char* s2); /// int strncmp(char* s1, char* s2, size_t n); /// -size_t strxfrm(char* s1, char* s2, size_t n); /// -void* memchr(void* s, int c, size_t n); /// char* strchr(char* s, int c); /// size_t strcspn(char* s1, char* s2); /// char* strpbrk(char* s1, char* s2); /// char* strrchr(char* s, int c); /// size_t strspn(char* s1, char* s2); /// char* strstr(char* s1, char* s2); /// -char* strtok(char* s1, char* s2); /// void* memset(void* s, int c, size_t n); /// -char* strerror(int errnum); /// int strlen(char* s); /// int strcmp(char* s1, char* s2); /// char* strcat(char* s1, char* s2); /// int memcmp(void* s1, void* s2, size_t n); /// +} +void* memmove(void* s1, void* s2, size_t n); /// +size_t strxfrm(char* s1, char* s2, size_t n); /// +int strcoll(char* s1, char* s2); /// +void* memchr(void* s, int c, size_t n); /// +char* strtok(char* s1, char* s2); /// +char* strerror(int errnum); /// version (Windows) { diff -uNrp dmd-1.004/src/phobos/std/c/time.d gdc-0.22/d/phobos/std/c/time.d --- dmd-1.004/src/phobos/std/c/time.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/time.d 2006-12-17 06:03:04.000000000 +0100 @@ -13,6 +13,26 @@ private import std.c.stddef; extern (C): +version (GNU) +{ + private import gcc.config; + alias gcc.config.CLOCKS_PER_SEC CLOCKS_PER_SEC; + alias gcc.config.Cclock_t clock_t; + alias gcc.config.Ctime_t time_t; + alias gcc.config.tm tm; + extern int daylight; + extern int timezone; + extern int altzone; + extern char *tzname[2]; + version (Windows) + { + const clock_t CLK_TCK = 1000; + } + // Else: not implemented yet. Could be be a constant or + // a sysconf() call depending on the OS. +} +else +{ alias int clock_t; version (Windows) @@ -64,6 +84,7 @@ struct tm tm_yday, tm_isdst; } +} clock_t clock(); time_t time(time_t *); diff -uNrp dmd-1.004/src/phobos/std/c/unix/unix.d gdc-0.22/d/phobos/std/c/unix/unix.d --- dmd-1.004/src/phobos/std/c/unix/unix.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/unix/unix.d 2006-09-04 16:11:36.000000000 +0200 @@ -0,0 +1,28 @@ +/* GDC -- D front-end for GCC + Copyright (C) 2004 David Friedman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +module std.c.unix.unix; + +/* This module imports the unix module for the currect + target system. Currently, all targets can be + handled with the autoconf'd version. */ + +public import gcc.configunix; + +// DMD linux.d has dirent.h declarations +public import std.c.dirent; diff -uNrp dmd-1.004/src/phobos/std/conv.d gdc-0.22/d/phobos/std/conv.d --- dmd-1.004/src/phobos/std/conv.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/conv.d 2007-01-31 01:52:39.000000000 +0100 @@ -105,7 +105,7 @@ int toInt(char[] s) goto Lerr; int sign = 0; - int v = 0; + uint v = 0; for (int i = 0; i < length; i++) { @@ -133,13 +133,13 @@ int toInt(char[] s) } if (sign == -1) { - if (cast(uint)v > 0x80000000) + if (v > 0x80000000) goto Loverflow; v = -v; } else { - if (cast(uint)v > 0x7FFFFFFF) + if (v > 0x7FFFFFFF) goto Loverflow; } return v; @@ -324,7 +324,7 @@ long toLong(char[] s) goto Lerr; int sign = 0; - long v = 0; + ulong v = 0; for (int i = 0; i < length; i++) { @@ -352,13 +352,13 @@ long toLong(char[] s) } if (sign == -1) { - if (cast(ulong)v > 0x8000000000000000) + if (v > 0x8000000000000000) goto Loverflow; v = -v; } else { - if (cast(ulong)v > 0x7FFFFFFFFFFFFFFF) + if (v > 0x7FFFFFFFFFFFFFFF) goto Loverflow; } return v; @@ -871,6 +871,18 @@ unittest * ditto */ +version (skyos) +{ + float strtof(char * s, char ** ep) { + return strtod(s, ep); + } +} + +static if (real.sizeof > double.sizeof) + private alias strtold _conv_strtold; +else + private alias strtod _conv_strtold; + float toFloat(in char[] s) { float f; @@ -878,6 +890,8 @@ float toFloat(in char[] s) char* sz; //writefln("toFloat('%s')", s); + version (aix) + s = toupper(s); sz = toStringz(s); if (std.ctype.isspace(*sz)) goto Lerr; @@ -888,7 +902,7 @@ float toFloat(in char[] s) f = strtof(sz, &endptr); if (getErrno() == ERANGE) goto Lerr; - if (endptr && (endptr == s.ptr || *endptr != 0)) + if (endptr && (endptr == sz || *endptr != 0)) goto Lerr; return f; @@ -942,6 +956,8 @@ double toDouble(in char[] s) char* sz; //writefln("toDouble('%s')", s); + version (aix) + s = toupper(s); sz = toStringz(s); if (std.ctype.isspace(*sz)) goto Lerr; @@ -952,7 +968,7 @@ double toDouble(in char[] s) f = strtod(sz, &endptr); if (getErrno() == ERANGE) goto Lerr; - if (endptr && (endptr == s.ptr || *endptr != 0)) + if (endptr && (endptr == sz || *endptr != 0)) goto Lerr; return f; @@ -1008,6 +1024,8 @@ real toReal(in char[] s) char* sz; //writefln("toReal('%s')", s); + version (aix) + s = toupper(s); sz = toStringz(s); if (std.ctype.isspace(*sz)) goto Lerr; @@ -1015,10 +1033,10 @@ real toReal(in char[] s) // BUG: should set __locale_decpoint to "." for DMC setErrno(0); - f = strtold(sz, &endptr); + f = _conv_strtold(sz, &endptr); if (getErrno() == ERANGE) goto Lerr; - if (endptr && (endptr == s.ptr || *endptr != 0)) + if (endptr && (endptr == sz || *endptr != 0)) goto Lerr; return f; @@ -1218,11 +1236,11 @@ cfloat toCfloat(in char[] s) // atof(s1); endptr = &s1[s1.length - 1]; - r1 = strtold(s1, &endptr); + r1 = _conv_strtold(s1, &endptr); // atof(s2); endptr = &s2[s2.length - 1]; - r2 = strtold(s2, &endptr); + r2 = _conv_strtold(s2, &endptr); cf = cast(cfloat)(r1 + (r2 * 1.0i)); @@ -1297,11 +1315,11 @@ cdouble toCdouble(in char[] s) // atof(s1); endptr = &s1[s1.length - 1]; - r1 = strtold(s1, &endptr); + r1 = _conv_strtold(s1, &endptr); // atof(s2); endptr = &s2[s2.length - 1]; - r2 = strtold(s2, &endptr); //atof(s2); + r2 = _conv_strtold(s2, &endptr); //atof(s2); cd = cast(cdouble)(r1 + (r2 * 1.0i)); @@ -1372,11 +1390,11 @@ creal toCreal(in char[] s) // atof(s1); endptr = &s1[s1.length - 1]; - r1 = strtold(s1, &endptr); + r1 = _conv_strtold(s1, &endptr); // atof(s2); endptr = &s2[s2.length - 1]; - r2 = strtold(s2, &endptr); //atof(s2); + r2 = _conv_strtold(s2, &endptr); //atof(s2); //writefln("toCreal() r1=%g, r2=%g, s1=\"%s\", s2=\"%s\", nan=%g", // r1, r2, s1, s2, creal.nan); diff -uNrp dmd-1.004/src/phobos/std/cpuid.d gdc-0.22/d/phobos/std/cpuid.d --- dmd-1.004/src/phobos/std/cpuid.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/cpuid.d 2006-12-17 06:03:04.000000000 +0100 @@ -34,6 +34,12 @@ COPYRIGHT: Public Domain * COPYRIGHT = Public Domain */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, November 2006 +*/ + module std.cpuid; import std.string; @@ -118,9 +124,9 @@ version(D_InlineAsm_X86) static this() { - getVendorString(); - getProcessorString(); - getFeatureFlags(); + getVendorString(vendorStr.ptr); + processorStr = getProcessorString(); + getFeatureFlags(& flags, & misc, & exflags, & apic, & signature); // stepping / family / model _stepping = signature&0xF; @@ -218,28 +224,30 @@ private: /* ** * fetches the cpu vendor string */ - private void getVendorString() + private void getVendorString(char* dst) { - char* dst = vendorStr.ptr; // puts the vendor string into dst asm { + push EBX ; mov EAX, 0 ; cpuid ; mov EAX, dst ; mov [EAX], EBX ; mov [EAX+4], EDX ; mov [EAX+8], ECX ; + db 0x5b /* pop EBX */ ; } } - private void getProcessorString() + private char[] getProcessorString() { char[48] buffer; char* dst = buffer.ptr; // puts the processor string into dst asm { + push EBX ; mov EAX, 0x8000_0000 ; cpuid ; cmp EAX, 0x8000_0004 ; @@ -266,20 +274,23 @@ private: mov [EDI+44], EDX ; pop EDI ; PSLabel: ; + db 0x5b /* pop EBX */ ; } if (buffer[0] == char.init) // no support - return; + return ""; // seems many intel processors prepend whitespace - processorStr = std.string.strip(std.string.toString(dst)).dup; + return std.string.strip(std.string.toString(dst)).dup; } - private void getFeatureFlags() + private void getFeatureFlags(uint *flags, uint *misc, uint *exflags, + uint *apic, uint *signature) { uint f,m,e,a,s; asm { + push EBX ; mov EAX, 0 ; cpuid ; cmp EAX, 1 ; @@ -301,13 +312,14 @@ private: mov e, EDX ; FeatLabel2: + db 0x5b /* pop EBX */ ; ; } - flags = f; - misc = m; - exflags = e; - apic = a; - signature = s; + *flags = f; + *misc = m; + *exflags = e; + *apic = a; + *signature = s; } private void getThreadingIntel() @@ -316,6 +328,7 @@ private: ubyte b = 0; asm { + push EBX ; mov EAX, 0 ; cpuid ; cmp EAX, 4 ; @@ -326,6 +339,7 @@ private: mov n, EAX ; mov b, 1 ; IntelSingle: ; + db 0x5b /* pop EBX */ ; } if (b != 0) { @@ -344,6 +358,7 @@ private: ubyte b = 0; asm { + push EBX ; mov EAX, 0x8000_0000 ; cpuid ; cmp EAX, 0x8000_0008 ; @@ -353,6 +368,7 @@ private: mov n, CL ; mov b, 1 ; AMDSingle: ; + db 0x5b /* pop EBX */ ; } if (b != 0) { diff -uNrp dmd-1.004/src/phobos/std/date.d gdc-0.22/d/phobos/std/date.d --- dmd-1.004/src/phobos/std/date.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/date.d 2007-02-06 05:30:00.000000000 +0100 @@ -17,6 +17,12 @@ // written by Walter Bright // www.digitalmars.com +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, May 2005 +*/ + module std.date; private import std.stdio; @@ -513,7 +519,7 @@ char[] toString(d_time time) DateFromTime(t), HourFromTime(t), MinFromTime(t), SecFromTime(t), sign, hr, mn, - cast(long)YearFromTime(t)); + /*cast(long)*/YearFromTime(t)); // Ensure no buggy buffer overflows //printf("len = %d, buffer.length = %d\n", len, buffer.length); @@ -577,7 +583,7 @@ char[] toDateString(d_time time) &daystr[WeekDay(t) * 3], &monstr[MonthFromTime(t) * 3], DateFromTime(t), - cast(long)YearFromTime(t)); + /*cast(long)*/YearFromTime(t)); // Ensure no buggy buffer overflows assert(len < buffer.length); @@ -822,7 +828,98 @@ version (Win32) } } -version (linux) +else version (GNU) +{ + // for now, just copy linux + private import std.c.unix.unix; + + d_time getUTCtime() + { timeval tv; + + if (gettimeofday(&tv, null)) + { // Some error happened - try time() instead + return time(null) * TicksPerSecond; + } + + return tv.tv_sec * cast(d_time)TicksPerSecond + + (tv.tv_usec / (1000000 / cast(d_time)TicksPerSecond)); + } + + private extern (C) time_t _d_gnu_cbridge_tza(); + + d_time getLocalTZA() + { + return _d_gnu_cbridge_tza() * TicksPerSecond; + /+ + int t; + tm * t_tm; + + time(&t); + t_tm = localtime(&t); // this will set timezone + // %%TODO: handle systems without tm_gmtoff + // %%TODO: configurate on _timezone instead of this.. + version (cygwin) { + return -_timzone * TicksPerSecond; + } else { + return t_tm.tm_gmtoff * TicksPerSecond; + } + +/ + } + + /* + * Get daylight savings time adjust for time dt. + */ + + int DaylightSavingTA(d_time dt) + { + tm *tmp; + time_t t; + int dst = 0; + + if (dt != d_time_nan) + { + d_time seconds = dt / TicksPerSecond; + t = cast(time_t) seconds; + if (t == seconds) // if in range + { + tmp = localtime(&t); + if (tmp.tm_isdst > 0) + dst = TicksPerHour; // BUG: Assume daylight savings time is plus one hour. + } + else // out of range for system time, use our own calculation + { // Daylight savings time goes from 2 AM the first Sunday + // in April through 2 AM the last Sunday in October + + dt -= LocalTZA; + + int year = YearFromTime(dt); + int leap = LeapYear(cast(int)dt); + //writefln("year = %s, leap = %s, month = %s", year, leap, MonthFromTime(dt)); + + d_time start = TimeFromYear(year); // Jan 1 + d_time end = start; + // Move fwd to Apr 1 + start += cast(d_time)(mdays[3] + leap) * TicksPerDay; + // Advance a day at a time until we find Sunday (0) + while (WeekDay(start) != 0) + start += TicksPerDay; + + // Move fwd to Oct 30 + end += cast(d_time)(mdays[9] + leap + 30) * TicksPerDay; + // Back up a day at a time until we find Sunday (0) + while (WeekDay(end) != 0) // 0 is Sunday + end -= TicksPerDay; + + dt -= 2 * TicksPerHour; // 2 AM + if (dt >= start && dt <= end) + dst = TicksPerHour; + //writefln("start = %s, dt = %s, end = %s, dst = %s", start, dt, end, dst); + } + } + return dst; + } +} +else version (linux) { private import std.c.linux.linux; @@ -842,7 +939,7 @@ version (linux) d_time getLocalTZA() { - __time_t t; + int t; time(&t); localtime(&t); // this will set timezone @@ -856,13 +953,13 @@ version (linux) int DaylightSavingTA(d_time dt) { tm *tmp; - std.c.linux.linux.__time_t t; + int t; int dst = 0; if (dt != d_time_nan) { d_time seconds = dt / TicksPerSecond; - t = cast(__time_t) seconds; + t = cast(int) seconds; if (t == seconds) // if in range { tmp = localtime(&t); @@ -876,7 +973,7 @@ version (linux) dt -= LocalTZA; int year = YearFromTime(dt); - int leap = LeapYear(cast(int)dt); + int leap = LeapYear(dt); //writefln("year = %s, leap = %s, month = %s", year, leap, MonthFromTime(dt)); d_time start = TimeFromYear(year); // Jan 1 diff -uNrp dmd-1.004/src/phobos/std/demangle.d gdc-0.22/d/phobos/std/demangle.d --- dmd-1.004/src/phobos/std/demangle.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/demangle.d 2006-12-17 06:03:04.000000000 +0100 @@ -5,6 +5,11 @@ * Placed into the Public Domain. */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, November 2005 +*/ /**** * Demangle D mangled names. * Macros: @@ -347,9 +352,9 @@ char[] demangle(char[] name) { real r; ubyte *p = cast(ubyte *)&r; - if (ni + 10 * 2 > name.length) + if (ni + real.sizeof * 2 > name.length) error(); - for (i = 0; i < 10; i++) + for (i = 0; i < real.sizeof; i++) { ubyte b; b = cast(ubyte) @@ -495,8 +500,12 @@ unittest [ "_D8demangle4testFLAiXi", "int demangle.test(lazy int[] ...)"] ]; - foreach (char[][2] name; table) + foreach (uint i, char[][2] name; table) { + static if (real.sizeof != 10) { + if (i == 7 || i == 8) + continue; + } char[] r = demangle(name[0]); //writefln("[ \"%s\", \"%s\" ],", name[0], r); assert(r == name[1]); diff -uNrp dmd-1.004/src/phobos/std/file.d gdc-0.22/d/phobos/std/file.d --- dmd-1.004/src/phobos/std/file.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/file.d 2007-02-03 17:34:12.000000000 +0100 @@ -27,10 +27,17 @@ * distribution. */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, March 2006 +*/ + module std.file; private import std.c.stdio; private import std.c.stdlib; +private import std.c.string; private import std.path; private import std.string; private import std.regexp; @@ -840,11 +847,13 @@ void copy(char[] from, char[] to) /* =========================== linux ======================= */ -version (linux) +else version (Unix) { +private import std.c.unix.unix; private import std.date; -private import std.c.linux.linux; + +alias std.c.unix.unix unix; extern (C) char* strerror(int); @@ -886,7 +895,7 @@ void[] read(char[] name) auto namez = toStringz(name); //printf("file.read('%s')\n",namez); - auto fd = std.c.linux.linux.open(namez, O_RDONLY); + auto fd = unix.open(namez, O_RDONLY); if (fd == -1) { //printf("\topen error, errno = %d\n",getErrno()); @@ -894,7 +903,7 @@ void[] read(char[] name) } //printf("\tfile opened\n"); - if (std.c.linux.linux.fstat(fd, &statbuf)) + if (unix.fstat(fd, &statbuf)) { //printf("\tfstat error, errno = %d\n",getErrno()); goto err2; @@ -904,14 +913,14 @@ void[] read(char[] name) if (buf.ptr) std.gc.hasNoPointers(buf.ptr); - numread = std.c.linux.linux.read(fd, cast(char*)buf, size); + numread = unix.read(fd, cast(char*)buf, size); if (numread != size) { //printf("\tread error, errno = %d\n",getErrno()); goto err2; } - if (std.c.linux.linux.close(fd) == -1) + if (unix.close(fd) == -1) { //printf("\tclose error, errno = %d\n",getErrno()); goto err; @@ -920,7 +929,7 @@ void[] read(char[] name) return buf; err2: - std.c.linux.linux.close(fd); + unix.close(fd); err: delete buf; @@ -941,21 +950,21 @@ void write(char[] name, void[] buffer) char *namez; namez = toStringz(name); - fd = std.c.linux.linux.open(namez, O_CREAT | O_WRONLY | O_TRUNC, 0660); + fd = unix.open(namez, O_CREAT | O_WRONLY | O_TRUNC, 0660); if (fd == -1) goto err; - numwritten = std.c.linux.linux.write(fd, buffer.ptr, buffer.length); + numwritten = unix.write(fd, buffer.ptr, buffer.length); if (buffer.length != numwritten) goto err2; - if (std.c.linux.linux.close(fd) == -1) + if (unix.close(fd) == -1) goto err; return; err2: - std.c.linux.linux.close(fd); + unix.close(fd); err: throw new FileException(name, getErrno()); } @@ -972,21 +981,21 @@ void append(char[] name, void[] buffer) char *namez; namez = toStringz(name); - fd = std.c.linux.linux.open(namez, O_APPEND | O_WRONLY | O_CREAT, 0660); + fd = unix.open(namez, O_APPEND | O_WRONLY | O_CREAT, 0660); if (fd == -1) goto err; - numwritten = std.c.linux.linux.write(fd, buffer.ptr, buffer.length); + numwritten = unix.write(fd, buffer.ptr, buffer.length); if (buffer.length != numwritten) goto err2; - if (std.c.linux.linux.close(fd) == -1) + if (unix.close(fd) == -1) goto err; return; err2: - std.c.linux.linux.close(fd); + unix.close(fd); err: throw new FileException(name, getErrno()); } @@ -1030,7 +1039,7 @@ ulong getSize(char[] name) namez = toStringz(name); //printf("file.getSize('%s')\n",namez); - fd = std.c.linux.linux.open(namez, O_RDONLY); + fd = unix.open(namez, O_RDONLY); if (fd == -1) { //printf("\topen error, errno = %d\n",getErrno()); @@ -1038,14 +1047,14 @@ ulong getSize(char[] name) } //printf("\tfile opened\n"); - if (std.c.linux.linux.fstat(fd, &statbuf)) + if (unix.fstat(fd, &statbuf)) { //printf("\tfstat error, errno = %d\n",getErrno()); goto err2; } size = statbuf.st_size; - if (std.c.linux.linux.close(fd) == -1) + if (unix.close(fd) == -1) { //printf("\tclose error, errno = %d\n",getErrno()); goto err; @@ -1054,7 +1063,7 @@ ulong getSize(char[] name) return size; err2: - std.c.linux.linux.close(fd); + unix.close(fd); err: err1: throw new FileException(name, getErrno()); @@ -1071,7 +1080,7 @@ uint getAttributes(char[] name) char *namez; namez = toStringz(name); - if (std.c.linux.linux.stat(namez, &statbuf)) + if (unix.stat(namez, &statbuf)) { throw new FileException(name, getErrno()); } @@ -1090,7 +1099,7 @@ void getTimes(char[] name, out d_time ft char *namez; namez = toStringz(name); - if (std.c.linux.linux.stat(namez, &statbuf)) + if (std.c.unix.unix.stat(namez, &statbuf)) { throw new FileException(name, getErrno()); } @@ -1114,7 +1123,7 @@ int exists(char[] name) char *namez; namez = toStringz(name); - if (std.c.linux.linux.stat(namez, &statbuf)) + if (unix.stat(namez, &statbuf)) { return 0; } @@ -1151,7 +1160,7 @@ int isdir(char[] name) void chdir(char[] pathname) { - if (std.c.linux.linux.chdir(toStringz(pathname))) + if (unix.chdir(toStringz(pathname))) { throw new FileException(pathname, getErrno()); } @@ -1163,7 +1172,7 @@ void chdir(char[] pathname) void mkdir(char[] pathname) { - if (std.c.linux.linux.mkdir(toStringz(pathname), 0777)) + if (unix.mkdir(toStringz(pathname), 0777)) { throw new FileException(pathname, getErrno()); } @@ -1175,7 +1184,7 @@ void mkdir(char[] pathname) void rmdir(char[] pathname) { - if (std.c.linux.linux.rmdir(toStringz(pathname))) + if (unix.rmdir(toStringz(pathname))) { throw new FileException(pathname, getErrno()); } @@ -1187,17 +1196,32 @@ void rmdir(char[] pathname) char[] getcwd() { - auto p = std.c.linux.linux.getcwd(null, 0); + version(all) + { + char buf[PATH_MAX]; + if (! unix.getcwd(buf.ptr, buf.length)) + { + throw new FileException("cannot get cwd", getErrno()); + } + size_t len = strlen(buf.ptr); + char[] result = new char[len]; + result[] = buf[0..len]; + return result; + } + else + { + auto p = unix.getcwd(null, 0); if (!p) { throw new FileException("cannot get cwd", getErrno()); } - auto len = std.string.strlen(p); auto buf = new char[len]; buf[] = p[0 .. len]; std.c.stdlib.free(p); return buf; + } + } /*************************************************** @@ -1211,24 +1235,44 @@ struct DirEntry d_time _creationTime = d_time_nan; // time of file creation d_time _lastAccessTime = d_time_nan; // time file was last accessed d_time _lastWriteTime = d_time_nan; // time file was last written to - ubyte d_type; + version (GNU) + typeof(struct_stat.st_mode) _st_mode; + else + ubyte d_type; ubyte didstat; // done lazy evaluation of stat() void init(char[] path, dirent *fd) { size_t len = std.string.strlen(fd.d_name.ptr); name = std.path.join(path, fd.d_name[0 .. len]); - d_type = fd.d_type; + version(GNU) + { } + else + d_type = fd.d_type; didstat = 0; } int isdir() { - return d_type & DT_DIR; + version(GNU) + { + if (!didstat) + doStat(); + return (_st_mode & S_IFMT) == S_IFDIR; + } + else + return d_type & DT_DIR; } int isfile() { - return d_type & DT_REG; + version(GNU) + { + if (!didstat) + doStat(); + return (_st_mode & S_IFMT) == S_IFREG; + } + else + return d_type & DT_REG; } ulong size() @@ -1270,7 +1314,7 @@ struct DirEntry char* namez; namez = toStringz(name); - if (std.c.linux.linux.stat(namez, &statbuf)) + if (std.c.unix.unix.stat(namez, &statbuf)) { //printf("\tstat error, errno = %d\n",getErrno()); return; @@ -1279,7 +1323,7 @@ struct DirEntry _creationTime = cast(d_time)statbuf.st_ctime * std.date.TicksPerSecond; _lastAccessTime = cast(d_time)statbuf.st_atime * std.date.TicksPerSecond; _lastWriteTime = cast(d_time)statbuf.st_mtime * std.date.TicksPerSecond; - + _st_mode = statbuf.st_mode; didstat = 1; } } @@ -1398,7 +1442,7 @@ void copy(char[] from, char[] to) char* toz = toStringz(to); //printf("file.copy(from='%s', to='%s')\n", fromz, toz); - int fd = std.c.linux.linux.open(fromz, O_RDONLY); + int fd = std.c.unix.unix.open(fromz, O_RDONLY); if (fd == -1) { //printf("\topen error, errno = %d\n",getErrno()); @@ -1406,13 +1450,13 @@ void copy(char[] from, char[] to) } //printf("\tfile opened\n"); - if (std.c.linux.linux.fstat(fd, &statbuf)) + if (std.c.unix.unix.fstat(fd, &statbuf)) { //printf("\tfstat error, errno = %d\n",getErrno()); goto err2; } - int fdw = std.c.linux.linux.open(toz, O_CREAT | O_WRONLY | O_TRUNC, 0660); + int fdw = std.c.unix.unix.open(toz, O_CREAT | O_WRONLY | O_TRUNC, 0660); if (fdw == -1) { //printf("\topen error, errno = %d\n",getErrno()); @@ -1434,13 +1478,13 @@ void copy(char[] from, char[] to) for (size_t size = statbuf.st_size; size; ) { size_t toread = (size > BUFSIZ) ? BUFSIZ : size; - auto n = std.c.linux.linux.read(fd, buf, toread); + auto n = std.c.unix.unix.read(fd, buf, toread); if (n != toread) { //printf("\tread error, errno = %d\n",getErrno()); goto err5; } - n = std.c.linux.linux.write(fdw, buf, toread); + n = std.c.unix.unix.write(fdw, buf, toread); if (n != toread) { //printf("\twrite error, errno = %d\n",getErrno()); @@ -1451,22 +1495,22 @@ void copy(char[] from, char[] to) std.c.stdlib.free(buf); - if (std.c.linux.linux.close(fdw) == -1) + if (std.c.unix.unix.close(fdw) == -1) { //printf("\tclose error, errno = %d\n",getErrno()); goto err2; } utimbuf utim; - utim.actime = cast(__time_t)statbuf.st_atime; - utim.modtime = cast(__time_t)statbuf.st_mtime; + utim.actime = cast(typeof(utim.actime))statbuf.st_atime; + utim.modtime = cast(typeof(utim.modtime))statbuf.st_mtime; if (utime(toz, &utim) == -1) { //printf("\tutime error, errno = %d\n",getErrno()); goto err3; } - if (std.c.linux.linux.close(fd) == -1) + if (std.c.unix.unix.close(fd) == -1) { //printf("\tclose error, errno = %d\n",getErrno()); goto err1; @@ -1477,11 +1521,11 @@ void copy(char[] from, char[] to) err5: std.c.stdlib.free(buf); err4: - std.c.linux.linux.close(fdw); + std.c.unix.unix.close(fdw); err3: std.c.stdio.remove(toz); err2: - std.c.linux.linux.close(fd); + std.c.unix.unix.close(fd); err1: throw new FileException(from, getErrno()); } diff -uNrp dmd-1.004/src/phobos/std/format.d gdc-0.22/d/phobos/std/format.d --- dmd-1.004/src/phobos/std/format.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/format.d 2007-01-27 17:44:01.000000000 +0100 @@ -45,6 +45,10 @@ version (Windows) { version = DigitalMarsC; } + version (GNU) + { + version = GNU_MinGW_MSVCRT; + } } version (DigitalMarsC) @@ -442,7 +446,8 @@ formattedPrint("The answer is %s:", x, 6 ------------------------ */ -void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr) +void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr, + void * p_args = null) { int j; TypeInfo ti; Mangle m; @@ -571,16 +576,24 @@ void doFormat(void delegate(dchar) putc, format[i + 0] = '*'; format[i + 1] = '.'; format[i + 2] = '*'; - format[i + 3] = 'L'; - format[i + 4] = fc; - format[i + 5] = 0; + i += 3; + version (GNU_MinGW_MSVCRT) + { /* nothing: no support for long double */ } + else + static if (real.sizeof > double.sizeof) + format[i++] = 'L'; + format[i++] = fc; + format[i] = 0; if (!(flags & FLprecision)) precision = -1; while (1) { int n; sl = fbuf.length; - n = snprintf(fbuf.ptr, sl, format.ptr, field_width, precision, v); + version (GNU_MinGW_MSVCRT) + n = snprintf(fbuf.ptr, sl, format.ptr, field_width, precision, cast(double) v); + else + n = snprintf(fbuf.ptr, sl, format.ptr, field_width, precision, v); //printf("format = '%s', n = %d\n", cast(char*)format, n); if (n >= 0 && n < sl) { sl = n; @@ -601,7 +614,7 @@ void doFormat(void delegate(dchar) putc, putc('['); size_t tsize = ti.tsize(); while (len--) { - doFormat(putc, (&ti)[0 .. 1], p); + doFormat(putc, (&ti)[0 .. 1], argptr, p); p += tsize; if (len > 0) putc(','); } @@ -609,6 +622,7 @@ void doFormat(void delegate(dchar) putc, } //printf("formatArg(fc = '%c', m = '%c')\n", fc, m); + if (! p_args) switch (m) { case Mangle.Tbit: @@ -703,7 +717,7 @@ void doFormat(void delegate(dchar) putc, goto Lputstr; case Mangle.Tpointer: - vnumber = cast(ulong)va_arg!(void*)(argptr); + vnumber = cast(size_t)va_arg!(void*)(argptr); uc = 1; flags |= FL0pad; if (!(flags & FLprecision)) @@ -717,14 +731,22 @@ void doFormat(void delegate(dchar) putc, case Mangle.Tfloat: case Mangle.Tifloat: if (fc == 'x' || fc == 'X') - goto Luint; + { + float f = va_arg!(float)(argptr); + vnumber = *cast(uint*)&f; + goto Lnumber; + } vreal = va_arg!(float)(argptr); goto Lreal; case Mangle.Tdouble: case Mangle.Tidouble: if (fc == 'x' || fc == 'X') - goto Lulong; + { + double f = va_arg!(double)(argptr); + vnumber = *cast(ulong*)&f; + goto Lnumber; + } vreal = va_arg!(double)(argptr); goto Lreal; @@ -800,14 +822,233 @@ void doFormat(void delegate(dchar) putc, case Mangle.Tstruct: { TypeInfo_Struct tis = cast(TypeInfo_Struct)ti; - s = tis.xtoString(argptr); - argptr += (tis.tsize() + 3) & ~3; + static if + ( + is( typeof(argptr): void[] ) || + is( typeof(argptr) == struct )) + { + version(PPC) + { + // Structs are pass-by-reference in V4 ABI + s = tis.xtoString(va_arg!(void*)(argptr)); + } + else + { + static assert(0, "uimplemented"); + } + } + else + { + s = tis.xtoString(argptr); + argptr += (tis.tsize() + 3) & ~3; + } goto Lputstr; } default: goto Lerror; } + else + { + switch (m) + { + case Mangle.Tbit: + case Mangle.Tbool: + vbit = *cast(bool*)(p_args); p_args += bool.sizeof; // int.sizeof, etc.? + if (fc != 's') + { vnumber = vbit; + goto Lnumber; + } + putstr(vbit ? "true" : "false"); + return; + + + case Mangle.Tchar: + vchar = *cast(char*)(p_args); p_args += char.sizeof; + if (fc != 's') + { vnumber = vchar; + goto Lnumber; + } + PL2: // there is goto L2 outside of thise switch; it's okay to do that + putstr((&vchar)[0 .. 1]); + return; + + case Mangle.Twchar: + vdchar = *cast(wchar*)(p_args); p_args += wchar.sizeof; + goto PL1; + + case Mangle.Tdchar: + vdchar = *cast(dchar*)(p_args); p_args += dchar.sizeof; + PL1: + if (fc != 's') + { vnumber = vdchar; + goto Lnumber; + } + if (vdchar <= 0x7F) + { vchar = cast(char)vdchar; + goto PL2; + } + else + { if (!isValidDchar(vdchar)) + throw new UtfException("invalid dchar in format", 0); + char[4] vbuf; + putstr(toUTF8(vbuf, vdchar)); + } + return; + + + case Mangle.Tbyte: + signed = 1; + vnumber = *cast(byte*)p_args; p_args += byte.sizeof; + goto Lnumber; + + case Mangle.Tubyte: + vnumber = *cast(ubyte*)p_args; p_args += ubyte.sizeof; + goto Lnumber; + + case Mangle.Tshort: + signed = 1; + vnumber = *cast(short*)p_args; p_args += short.sizeof; + goto Lnumber; + + case Mangle.Tushort: + vnumber = *cast(ushort*)p_args; p_args += ushort.sizeof; + goto Lnumber; + + case Mangle.Tint: + signed = 1; + vnumber = *cast(int*)p_args; p_args += int.sizeof; + goto Lnumber; + + case Mangle.Tuint: + PLuint: + vnumber = *cast(uint*)p_args; p_args += uint.sizeof; + goto Lnumber; + + case Mangle.Tlong: + signed = 1; + vnumber = cast(ulong)*cast(long*)p_args; p_args += long.sizeof; + goto Lnumber; + + case Mangle.Tulong: + PLulong: + vnumber = *cast(ulong*)p_args; p_args += ulong.sizeof; + goto Lnumber; + + case Mangle.Tclass: + vobject = *cast(Object*)p_args; p_args += Object.sizeof; + s = vobject.toString(); + goto Lputstr; + + case Mangle.Tpointer: + alias void * void_ponter_t; + vnumber = cast(size_t)*cast(void**)p_args; p_args += void_ponter_t.sizeof; + uc = 1; + flags |= FL0pad; + if (!(flags & FLprecision)) + { flags |= FLprecision; + precision = (void*).sizeof; + } + base = 16; + goto Lnumber; + + + case Mangle.Tfloat: + case Mangle.Tifloat: + if (fc == 'x' || fc == 'X') + goto PLuint; + vreal = *cast(float*)p_args; p_args += float.sizeof; + goto Lreal; + + case Mangle.Tdouble: + case Mangle.Tidouble: + if (fc == 'x' || fc == 'X') + goto PLulong; + vreal = *cast(double*)p_args; p_args += double.sizeof; + goto Lreal; + + case Mangle.Treal: + case Mangle.Tireal: + vreal = *cast(real*)p_args; p_args += real.sizeof; + goto Lreal; + + + case Mangle.Tcfloat: + vcreal = *cast(cfloat*)p_args; p_args += cfloat.sizeof; + goto Lcomplex; + + case Mangle.Tcdouble: + vcreal = *cast(cdouble*)p_args; p_args += cdouble.sizeof; + goto Lcomplex; + + case Mangle.Tcreal: + vcreal = *cast(creal*)p_args; p_args += creal.sizeof; + goto Lcomplex; + + case Mangle.Tarray: + alias void[] array_t; + if (ti.classinfo.name.length == 14 && + ti.classinfo.name[9..14] == "Array") + { // array of non-primitive types + void[] va = *cast(void[]*)p_args; p_args += array_t.sizeof; + putArray(va.ptr, va.length, (cast(TypeInfo_Array)ti).next); + return; + } + m2 = cast(Mangle)ti.classinfo.name[10]; + switch (m2) + { + case Mangle.Tchar: + s = *cast(char[]*)p_args; p_args += array_t.sizeof; + goto PLputstr; + + case Mangle.Twchar: + wchar[] sw = *cast(wchar[]*)p_args; p_args += array_t.sizeof; + s = toUTF8(sw); + goto PLputstr; + + case Mangle.Tdchar: + dchar[] sd = *cast(dchar[]*)p_args; p_args += array_t.sizeof; + s = toUTF8(sd); + PLputstr: + if (fc != 's') + throw new FormatError("string"); + if (flags & FLprecision && precision < s.length) + s = s[0 .. precision]; + putstr(s); + break; + + default: + TypeInfo ti2 = primitiveTypeInfo(m2); + if (!ti2) + goto Lerror; + void[] va = *cast(void[]*)p_args; p_args += array_t.sizeof; + putArray(va.ptr, va.length, ti2); + } + return; + + case Mangle.Ttypedef: + ti = (cast(TypeInfo_Typedef)ti).base; + m = cast(Mangle)ti.classinfo.name[9]; + formatArg(fc); + return; + + case Mangle.Tenum: + ti = (cast(TypeInfo_Enum)ti).base; + m = cast(Mangle)ti.classinfo.name[9]; + formatArg(fc); + return; + + case Mangle.Tstruct: + { TypeInfo_Struct tis = cast(TypeInfo_Struct)ti; + s = tis.xtoString(p_args); + p_args += tis.tsize(); + goto Lputstr; + } + + default: + goto Lerror; + } + } Lnumber: switch (fc) @@ -957,6 +1198,7 @@ void doFormat(void delegate(dchar) putc, * to deal with UTF in a couple of isolated spots. */ + if (! p_args) switch (m2) { case Mangle.Tchar: @@ -977,6 +1219,30 @@ void doFormat(void delegate(dchar) putc, formatArg('s'); continue; } + else + { + alias void[] array_t; + switch (m2) + { + case Mangle.Tchar: + fmt = *cast(char[]*)p_args; p_args += array_t.sizeof; + break; + + case Mangle.Twchar: + wfmt = *cast(wchar[]*)p_args; p_args += array_t.sizeof; + fmt = toUTF8(wfmt); + break; + + case Mangle.Tdchar: + dfmt = *cast(dchar[]*)p_args; p_args += array_t.sizeof; + fmt = toUTF8(dfmt); + break; + + default: + formatArg('s'); + continue; + } + } for (size_t i = 0; i < fmt.length; ) { dchar c = fmt[i++]; @@ -1013,7 +1279,13 @@ void doFormat(void delegate(dchar) putc, m = cast(Mangle)ti.classinfo.name[9]; if (m != Mangle.Tint) throw new FormatError("int argument expected"); + if (! p_args) return va_arg!(int)(argptr); + else + { + int result = *cast(int*)(p_args); p_args += int.sizeof; + return result; + } } if (c != '%') @@ -1115,6 +1387,9 @@ Lerror: /* ======================== Unit Tests ====================================== */ +version (skyos) + version = no_hexfloat; + unittest { int i; @@ -1130,10 +1405,16 @@ unittest * C99 doesn't specify what the hex digit before the decimal point * is for %A. */ - version (linux) - assert(s == "1.67 -0XA.3D70A3D70A3D8P-3 nan"); + /* + printf("%.*s\n", s); + printf("d: %A\n", -1.28); + printf("r: %LA\n", -1.28L); + */ + version (no_hexfloat) + { /*nothing*/ } else - assert(s == "1.67 -0X1.47AE147AE147BP+0 nan"); + assert(s == "1.67 -0XA.3D70A3D70A3D8P-3 nan" || + s == "1.67 -0X1.47AE147AE147BP+0 nan"); s = std.string.format("%x %X", 0x1234AF, 0xAFAFAFAF); assert(s == "1234af AFAFAFAF"); diff -uNrp dmd-1.004/src/phobos/std/intrinsic.d gdc-0.22/d/phobos/std/intrinsic.d --- dmd-1.004/src/phobos/std/intrinsic.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/intrinsic.d 2006-06-02 05:31:29.000000000 +0200 @@ -4,6 +4,12 @@ // www.digitalmars.com // Placed into the public domain +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, May 2006 +*/ + /** These functions are built-in intrinsics to the compiler. * Intrinsic functions are functions built in to the compiler, @@ -26,7 +32,19 @@ module std.intrinsic; * The bit number of the first bit set. * The return value is undefined if v is zero. */ -int bsf(uint v); +version (GNU) + int bsf(uint v) + { + uint m = 1; + uint i; + for (i = 0; i < 32; i++,m<<=1) { + if (v&m) + return i; + } + return i; // supposed to be undefined + } +else + int bsf(uint v); /** * Scans the bits in v from the most significant bit @@ -56,22 +74,60 @@ int bsf(uint v); * bsf(x21) = 0
* bsr(x21) = 5 */ -int bsr(uint v); +version (GNU) +int bsr(uint v) +{ + uint m = 0x80000000; + uint i; + for (i = 32; i ; i--,m>>>=1) { + if (v&m) + return i-1; + } + return i; // supposed to be undefined +} +else + int bsr(uint v); /** * Tests the bit. */ -int bt(uint *p, uint bitnum); +version (GNU) +int bt(uint *p, uint bitnum) +{ + return (p[bitnum / (uint.sizeof*8)] & (1<<(bitnum & ((uint.sizeof*8)-1)))) ? -1 : 0 ; +} +else + int bt(uint *p, uint bitnum); /** * Tests and complements the bit. */ +version (GNU) +int btc(uint *p, uint bitnum) +{ + uint * q = p + (bitnum / (uint.sizeof*8)); + uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1)); + int result = *q & mask; + *q ^= mask; + return result ? -1 : 0; +} +else int btc(uint *p, uint bitnum); /** * Tests and resets (sets to 0) the bit. */ -int btr(uint *p, uint bitnum); +version (GNU) +int btr(uint *p, uint bitnum) +{ + uint * q = p + (bitnum / (uint.sizeof*8)); + uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1)); + int result = *q & mask; + *q &= ~mask; + return result ? -1 : 0; +} +else + int btr(uint *p, uint bitnum); /** * Tests and sets the bit. @@ -129,7 +185,17 @@ bt(array, 1) = -1 array = [0]:x2, [1]:x100 */ -int bts(uint *p, uint bitnum); +version (GNU) +int bts(uint *p, uint bitnum) +{ + uint * q = p + (bitnum / (uint.sizeof*8)); + uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1)); + int result = *q & mask; + *q |= mask; + return result ? -1 : 0; +} +else + int bts(uint *p, uint bitnum); /** @@ -137,38 +203,62 @@ int bts(uint *p, uint bitnum); byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3 becomes byte 0. */ -uint bswap(uint v); +version (GNU) +uint bswap(uint v) +{ + return ((v&0xFF)<<24)|((v&0xFF00)<<8)|((v&0xFF0000)>>>8)|((v&0xFF000000)>>>24); +} +else + uint bswap(uint v); /** * Reads I/O port at port_address. */ -ubyte inp(uint port_address); +version (GNU) + ubyte inp(uint p) { return 0; } +else + ubyte inp(uint port_address); /** * ditto */ -ushort inpw(uint port_address); +version (GNU) + ushort inpw(uint p) { return 0; } +else + ushort inpw(uint port_address); /** * ditto */ -uint inpl(uint port_address); +version (GNU) + uint inpl(uint p) { return 0; } +else + uint inpl(uint port_address); /** * Writes and returns value to I/O port at port_address. */ -ubyte outp(uint port_address, ubyte value); +version (GNU) + ubyte outp(uint p, ubyte v) { return v; } +else + ubyte outp(uint port_address, ubyte value); /** * ditto */ -ushort outpw(uint port_address, ushort value); +version (GNU) + ushort outpw(uint p, ushort v) { return v; } +else + ushort outpw(uint port_address, ushort value); /** * ditto */ -uint outpl(uint port_address, uint value); +version (GNU) + uint outpl(uint p, uint v) { return v; } +else + uint outpl(uint port_address, uint value); diff -uNrp dmd-1.004/src/phobos/std/loader.d gdc-0.22/d/phobos/std/loader.d --- dmd-1.004/src/phobos/std/loader.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/loader.d 2006-12-17 06:03:04.000000000 +0100 @@ -8,7 +8,7 @@ * * Author: Matthew Wilson * - * License: (Licensed under the Synesis Software Standard Source License) + * License: * * Copyright (C) 2002-2004, Synesis Software Pty Ltd. * @@ -20,25 +20,19 @@ * email: submissions@synsoft.org for submissions * admin@synsoft.org for other enquiries * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * (i) Redistributions of source code must retain the above - * copyright notice and contact information, this list of - * conditions and the following disclaimer. - * - * (ii) Any derived versions of this software (howsoever modified) - * remain the sole property of Synesis Software. - * - * (iii) Any derived versions of this software (howsoever modified) - * remain subject to all these conditions. - * - * (iv) Neither the name of Synesis Software nor the names of any - * subdivisions, employees or agents of Synesis Software, nor the - * names of any other contributors to this software may be used to - * endorse or promote products derived from this software without - * specific prior written permission. + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, in both source and binary form, subject to the following + * restrictions: + * + * - The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * - Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * - This notice may not be removed or altered from any source + * distribution. * * This source code is provided by Synesis Software "as is" and any * warranties, whether expressed or implied, including, but not @@ -56,6 +50,36 @@ * * ////////////////////////////////////////////////////////////////////////// */ +/* + Copyright for Darwin specific code + + Copyright (c) 2002 Peter O'Gorman + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, June 2006 (applied patches from Anders F Björklund.) +*/ /** \file D/std/loader.d This file contains the \c D standard library @@ -84,6 +108,11 @@ public alias int bool * External function declarations */ +version(linux) + version = dlopen; +else version (freebsd) + version = dlopen; + version(Windows) { private import std.c.windows.windows; @@ -94,7 +123,7 @@ version(Windows) alias HMODULE HModule_; } } -else version(linux) +else version(dlopen) { extern(C) { @@ -110,6 +139,104 @@ else version(linux) char* strerror(int); } } +else version(darwin) +{ + extern(C) + { + // #include + + struct mach_header + { + uint magic; /* mach magic number identifier */ + uint cputype; /* cpu specifier */ + uint cpusubtype; /* machine specifier */ + uint filetype; /* type of file */ + uint ncmds; /* number of load commands */ + uint sizeofcmds; /* the size of all the load commands */ + uint flags; /* flags */ + } + + /* Constant for the magic field of the mach_header */ + const uint MH_MAGIC = 0xfeedface; // the mach magic number + const uint MH_CIGAM = 0xcefaedfe; // x86 variant + + // #include + + typedef void *NSObjectFileImage; + + typedef void *NSModule; + + typedef void *NSSymbol; + + enum // DYLD_BOOL: uint + { + FALSE, + TRUE + } + alias uint DYLD_BOOL; + + enum // NSObjectFileImageReturnCode: uint + { + NSObjectFileImageFailure, /* for this a message is printed on stderr */ + NSObjectFileImageSuccess, + NSObjectFileImageInappropriateFile, + NSObjectFileImageArch, + NSObjectFileImageFormat, /* for this a message is printed on stderr */ + NSObjectFileImageAccess + } + alias uint NSObjectFileImageReturnCode; + + enum // NSLinkEditErrors: uint + { + NSLinkEditFileAccessError, + NSLinkEditFileFormatError, + NSLinkEditMachResourceError, + NSLinkEditUnixResourceError, + NSLinkEditOtherError, + NSLinkEditWarningError, + NSLinkEditMultiplyDefinedError, + NSLinkEditUndefinedError + } + alias uint NSLinkEditErrors; + + + alias NSModule HModule_; + + NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(char *pathName, NSObjectFileImage* objectFileImage); + DYLD_BOOL NSDestroyObjectFileImage(NSObjectFileImage objectFileImage); + + mach_header * NSAddImage(char *image_name, uint options); + const uint NSADDIMAGE_OPTION_NONE = 0x0; + const uint NSADDIMAGE_OPTION_RETURN_ON_ERROR = 0x1; + const uint NSADDIMAGE_OPTION_WITH_SEARCHING = 0x2; + const uint NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED = 0x4; + const uint NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME = 0x8; + + NSModule NSLinkModule(NSObjectFileImage objectFileImage, char* moduleName, uint options); + const uint NSLINKMODULE_OPTION_NONE = 0x0; + const uint NSLINKMODULE_OPTION_BINDNOW = 0x01; + const uint NSLINKMODULE_OPTION_PRIVATE = 0x02; + const uint NSLINKMODULE_OPTION_RETURN_ON_ERROR = 0x04; + const uint NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES = 0x08; + const uint NSLINKMODULE_OPTION_TRAILING_PHYS_NAME = 0x10; + DYLD_BOOL NSUnLinkModule(NSModule module_, uint options); + + void NSLinkEditError(NSLinkEditErrors *c, int *errorNumber, char **fileName, char **errorString); + + DYLD_BOOL NSIsSymbolNameDefined(char *symbolName); + DYLD_BOOL NSIsSymbolNameDefinedInImage(mach_header *image, char *symbolName); + NSSymbol NSLookupAndBindSymbol(char *symbolName); + NSSymbol NSLookupSymbolInModule(NSModule module_, char* symbolName); + NSSymbol NSLookupSymbolInImage(mach_header *image, char *symbolName, uint options); + const uint NSLOOKUPSYMBOLINIMAGE_OPTION_BIND = 0x0; + const uint NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW = 0x1; + const uint NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY = 0x2; + const uint NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR = 0x4; + + void* NSAddressOfSymbol(NSSymbol symbol); + char* NSNameOfSymbol(NSSymbol symbol); + } +} else { const int platform_not_discriminated = 0; @@ -285,7 +412,7 @@ version(Windows) return szFileName[0 .. cch].dup; } } -else version(linux) +else version(dlopen) { private class ExeModuleInfo { @@ -326,7 +453,7 @@ else version(linux) private void ExeModule_Uninit_() { if(0 == --s_init) - { + { } } @@ -337,11 +464,11 @@ else version(linux) } body { - ExeModuleInfo mi = s_modules[moduleName]; + ExeModuleInfo *p_mi = moduleName in s_modules; - if(null !is mi) + if(p_mi != null) { - return (++mi.m_cRefs, cast(HXModule)mi); + return (++(*p_mi).m_cRefs, cast(HXModule)*p_mi); } else { @@ -416,7 +543,7 @@ else version(linux) { record_error_(); } - delete s_modules[name]; + s_modules.remove(name); delete mi; } @@ -474,6 +601,258 @@ else version(linux) return mi.m_name; } } +else version(darwin) +{ + private class ExeModuleInfo + { + public: + int m_cRefs; + HModule_ m_hmod; + char[] m_name; + + this(HModule_ hmod, char[] name) + { + m_cRefs = 1; + m_hmod = hmod; + m_name = name; + } + }; + + private void record_error_() + { + NSLinkEditErrors error; + int errno; + char *fileName; + char *err = null; + + NSLinkEditError(&error, &errno, &fileName, &err); + printf("NSLinkEditError: %d %d - %s %s\n", cast(uint) error, errno, fileName, err); + + s_lastError = (err == null) ? "" : err[0 .. std.string.strlen(err)]; + } + + private int s_init; + private ExeModuleInfo [char[]] s_modules; + private char[] s_lastError; // This is NOT thread-specific + + private int ExeModule_Init_() + { + if(1 == ++s_init) + { + return 0; + } + + return 1; + } + + private void ExeModule_Uninit_() + { + if(0 == --s_init) + { + } + } + + private HXModule ExeModule_Load_(in char[] moduleName) + in + { + assert(null !is moduleName); + } + body + { + ExeModuleInfo *p_mi = moduleName in s_modules; + + if(p_mi != null) + { + return (++(*p_mi).m_cRefs, cast(HXModule)*p_mi); + } + else + { + NSModule handle = null; + NSObjectFileImage fileImage = null; + char * filename = toStringz(moduleName); + // printf("DEBUG Trying to load: %s\n", filename); + + NSObjectFileImageReturnCode returnCode = + NSCreateObjectFileImageFromFile(filename, &fileImage); + if(returnCode == NSObjectFileImageSuccess) + { + handle = NSLinkModule(fileImage,filename, + NSLINKMODULE_OPTION_RETURN_ON_ERROR | + NSLINKMODULE_OPTION_PRIVATE | + NSLINKMODULE_OPTION_BINDNOW); + NSDestroyObjectFileImage(fileImage); + } + else if(returnCode == NSObjectFileImageInappropriateFile) + { + NSDestroyObjectFileImage(fileImage); + /* Could be dynamic library rather than a bundle */ + handle = cast(NSModule) NSAddImage(filename, + NSADDIMAGE_OPTION_RETURN_ON_ERROR); + } + else + { + // printf("Failed: %d\n", returnCode); + s_lastError = "NSCreateObjectFileImageFromFile failed"; + return null; + } + + if (handle == null) + { + record_error_(); + + return null; + } + else + { + ExeModuleInfo mi = new ExeModuleInfo(handle, moduleName); + + s_modules[moduleName] = mi; + + return cast(HXModule)mi; + } + } + } + + private HXModule ExeModule_AddRef_(in HXModule hModule) + in + { + assert(null !is hModule); + + ExeModuleInfo mi = cast(ExeModuleInfo)hModule; + + assert(0 < mi.m_cRefs); + assert(null !is mi.m_hmod); + assert(null !is mi.m_name); + assert(null !is s_modules[mi.m_name]); + assert(mi is s_modules[mi.m_name]); + } + body + { + ExeModuleInfo mi = cast(ExeModuleInfo)hModule; + + if(null !is mi) + { + return (++mi.m_cRefs, hModule); + } + else + { + return null; + } + } + + private void ExeModule_Release_(inout HXModule hModule) + in + { + assert(null !is hModule); + + ExeModuleInfo mi = cast(ExeModuleInfo)hModule; + + assert(0 < mi.m_cRefs); + assert(null !is mi.m_hmod); + assert(null !is mi.m_name); + assert(null !is s_modules[mi.m_name]); + assert(mi is s_modules[mi.m_name]); + } + body + { + ExeModuleInfo mi = cast(ExeModuleInfo)hModule; + + if(0 == --mi.m_cRefs) + { + char[] name = mi.m_name; + uint magic; + + magic = (* cast(mach_header *) mi.m_hmod).magic; + if ( magic == MH_MAGIC || magic == MH_CIGAM ) + { + // Can not unlink dynamic libraries on Darwin + } + else if (NSUnLinkModule(mi.m_hmod, 0) == FALSE) + { + // printf("DEBUG: Could not unlink module %.*s\n", name); + } + s_modules.remove(name); + delete mi; + } + + hModule = null; + } + + private void *ExeModule_GetSymbol_(inout HXModule hModule, in char[] symbolName) + in + { + assert(null !is hModule); + + ExeModuleInfo mi = cast(ExeModuleInfo)hModule; + + assert(0 < mi.m_cRefs); + assert(null !is mi.m_hmod); + assert(null !is mi.m_name); + assert(null !is s_modules[mi.m_name]); + assert(mi is s_modules[mi.m_name]); + } + body + { + ExeModuleInfo mi = cast(ExeModuleInfo)hModule; + + NSModule handle = mi.m_hmod; + uint magic = (* cast(mach_header *) handle).magic; + char *name = ("_" ~ symbolName ~ "\0").ptr; + NSSymbol symbol = null; + + if ( (handle == cast(NSModule) -1) && + NSIsSymbolNameDefined(name)) + /* Global context, use NSLookupAndBindSymbol */ + symbol = NSLookupAndBindSymbol(name); + else if ( ( magic == MH_MAGIC || magic == MH_CIGAM ) && + NSIsSymbolNameDefinedInImage(cast(mach_header *) handle, name)) + symbol = NSLookupSymbolInImage(cast(mach_header *) handle, name, + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | + NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); + else + symbol = NSLookupSymbolInModule(handle, name); + + if (symbol == null) + { + // printf("DEBUG: Symbol not found: %s\n", name); + return null; + } + + void *address = NSAddressOfSymbol(symbol); + + if(address == null) + { + record_error_(); + } + + return address; + } + + private char[] ExeModule_Error_() + { + return s_lastError; + } + + private char[] ExeModule_GetPath_(HXModule hModule) + in + { + assert(null !is hModule); + + ExeModuleInfo mi = cast(ExeModuleInfo)hModule; + + assert(0 < mi.m_cRefs); + assert(null !is mi.m_hmod); + assert(null !is mi.m_name); + assert(null !is s_modules[mi.m_name]); + assert(mi is s_modules[mi.m_name]); + } + body + { + ExeModuleInfo mi = cast(ExeModuleInfo)hModule; + + return mi.m_name; + } +} else { const int platform_not_discriminated = 0; @@ -527,10 +906,14 @@ public: if (m_hModule == null) throw new ExeModuleException(GetLastError()); } - else version (linux) + else version (dlopen) { m_hModule = ExeModule_AddRef(hModule); } + else version (darwin) + { + m_hModule = ExeModule_AddRef(hModule); + } else static assert(0); } @@ -549,12 +932,18 @@ public: if (null is m_hModule) throw new ExeModuleException(GetLastError()); } - else version (linux) + else version (dlopen) { m_hModule = ExeModule_Load(moduleName); if (null is m_hModule) throw new ExeModuleException(ExeModule_Error()); } + else version (darwin) + { + m_hModule = ExeModule_Load(moduleName); + if (null is m_hModule) + throw new ExeModuleException(ExeModule_Error()); + } else { static assert(0); // unsupported system @@ -582,10 +971,14 @@ public: if(!FreeLibrary(cast(HModule_)m_hModule)) throw new ExeModuleException(GetLastError()); } - else version (linux) + else version (dlopen) { ExeModule_Release(m_hModule); } + else version (darwin) + { + ExeModule_Release(m_hModule); + } else static assert(0); } @@ -610,7 +1003,7 @@ public: throw new ExeModuleException(GetLastError()); } } - else version (linux) + else version (dlopen) { void *symbol = ExeModule_GetSymbol(m_hModule, symbolName); @@ -619,6 +1012,15 @@ public: throw new ExeModuleException(ExeModule_Error()); } } + else version (darwin) + { + void *symbol = ExeModule_GetSymbol(m_hModule, symbolName); + + if(null is symbol) + { + throw new ExeModuleException(ExeModule_Error()); + } + } else { static assert(0); @@ -666,10 +1068,14 @@ public: return szFileName[0 .. cch].dup; } - else version (linux) + else version (dlopen) { return ExeModule_GetPath_(m_hModule); } + else version (darwin) + { + return ExeModule_GetPath_(m_hModule); + } else static assert(0); } diff -uNrp dmd-1.004/src/phobos/std/math2.d gdc-0.22/d/phobos/std/math2.d --- dmd-1.004/src/phobos/std/math2.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/math2.d 2006-12-17 06:03:04.000000000 +0100 @@ -10,9 +10,19 @@ * the suitability of this software for any purpose. It is provided * "as is" without express or implied warranty. */ + +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ module std.math2; private import std.math, std.string, std.c.stdlib, std.c.stdio; +version(GNU) +{ + private import gcc.config; +} //debug=math2; @@ -80,17 +90,30 @@ private ushort fp_cw_chop = 7999; * Integer part */ -real trunc(real n) +version (GNU) { - ushort cw; - asm - { - fstcw cw; - fldcw fp_cw_chop; - fld n; - frndint; - fldcw cw; - } + version (GNU_Need_trunc) { + real trunc(real n) { + return n >= 0 ? std.math.floor(n) : std.math.ceil(n); + } + } else { + alias gcc.config.truncl trunc; + } +} +else +{ + real trunc(real n) + { + ushort cw; + asm + { + fstcw cw; + fldcw fp_cw_chop; + fld n; + frndint; + fldcw cw; + } + } } unittest @@ -464,7 +487,7 @@ unittest real acot(real x) { - return tan(1.0 / x); + return std.math.tan(1.0 / x); } unittest @@ -519,6 +542,10 @@ unittest real cot(real x) { + version(GNU) { + // %% is the asm below missing fld1? + return 1/gcc.config.tanl(x); + } else { asm { fld x; @@ -526,6 +553,7 @@ real cot(real x) fdivrp; fwait; } + } } unittest @@ -539,6 +567,9 @@ unittest real sec(real x) { + version(GNU) { + return 1/gcc.config.cosl(x); + } else { asm { fld x; @@ -547,6 +578,7 @@ real sec(real x) fdivrp; fwait; } + } } @@ -556,6 +588,10 @@ real sec(real x) real cosec(real x) { + version(GNU) { + // %% is the asm below missing fld1? + return 1/gcc.config.sinl(x); + } else { asm { fld x; @@ -564,6 +600,7 @@ real cosec(real x) fdivrp; fwait; } + } } /********************************************* @@ -573,6 +610,9 @@ real cosec(real x) /+ real frexp(real x, out int exponent) { + version (GNU) { + return gcc.config.frexpl(x, & exponent); + } else { asm { fld x; @@ -595,13 +635,14 @@ real frexp(real x, out int exponent) done: fwait; } + } } unittest { int exponent; real mantissa = frexp(123.456, exponent); - assert(feq(mantissa * pow(2.0L, cast(real)exponent), 123.456)); + assert(feq(mantissa * std.math.pow(2.0L, cast(real)exponent), 123.456)); } +/ @@ -611,12 +652,19 @@ unittest real coth(real x) { - return 1 / tanh(x); + return 1 / std.math.tanh(x); } unittest { - assert(feq(coth(1), cosh(1) / sinh(1))); + real r1 = coth(1); + real r2 = std.math.sinh(1); + real r3 = std.math.tanh(1); + real r4 = coth(1); + printf("%0.5Lg %0.5Lg %0.5Lg %0.5Lg\n", r1, r2, r3, r4); + printf("%0.5g %0.5g %0.5g %0.5g\n", + coth(1), std.math.sinh(1), std.math.tanh(1), coth(1)); + assert(feq(coth(1), std.math.cosh(1) / std.math.sinh(1))); } /************************************* @@ -625,7 +673,7 @@ unittest real sech(real x) { - return 1 / cosh(x); + return 1 / std.math.cosh(x); } /************************************* @@ -634,7 +682,7 @@ real sech(real x) real cosech(real x) { - return 1 / sinh(x); + return 1 / std.math.sinh(x); } /************************************* @@ -655,7 +703,7 @@ real acosh(real x) unittest { assert(acosh(0.5) == 0); - assert(feq(acosh(cosh(3)), 3)); + assert(feq(acosh(std.math.cosh(3)), 3)); } +/ @@ -676,15 +724,15 @@ real asinh(real x) { real z = x * x; return x > 0 ? - log1p(x + z / (1.0 + std.math.sqrt(1.0 + z))) : - -log1p(-x + z / (1.0 + std.math.sqrt(1.0 + z))); + std.math.log1p(x + z / (1.0 + std.math.sqrt(1.0 + z))) : + -std.math.log1p(-x + z / (1.0 + std.math.sqrt(1.0 + z))); } } unittest { assert(asinh(0) == 0); - assert(feq(asinh(sinh(3)), 3)); + assert(feq(asinh(std.math.sinh(3)), 3)); } +/ @@ -704,15 +752,15 @@ real atanh(real x) return -real.max; else return x > 0 ? - 0.5 * log1p((2.0 * x) / (1.0 - x)) : - -0.5 * log1p((-2.0 * x) / (1.0 + x)); + 0.5 * std.math.log1p((2.0 * x) / (1.0 - x)) : + -0.5 * std.math.log1p((-2.0 * x) / (1.0 + x)); } } unittest { assert(atanh(0) == 0); - assert(feq(atanh(tanh(0.5)), 0.5)); + assert(feq(atanh(std.math.tanh(0.5)), 0.5)); } +/ @@ -881,7 +929,7 @@ real atof(char[] s) } if (eneg) e = -e; - result *= pow(hex ? 2.0L : 10.0L, cast(real)e); + result *= std.math.pow(hex ? 2.0L : 10.0L, cast(real)e); done: return neg ? -result : result; } diff -uNrp dmd-1.004/src/phobos/std/math.d gdc-0.22/d/phobos/std/math.d --- dmd-1.004/src/phobos/std/math.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/math.d 2006-12-17 06:03:04.000000000 +0100 @@ -51,6 +51,12 @@ * */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2005 +*/ + module std.math; @@ -61,6 +67,15 @@ private import std.c.stdio; private import std.string; private import std.c.math; +version (GNU) +{ + private import gcc.config; + + // Some functions are missing from msvcrt... + version (Windows) + version = GNU_msvcrt_math; +} + class NotImplemented : Error { this(char[] msg) @@ -145,7 +160,7 @@ unittest assert(abs(71.6Li) == 71.6L); assert(abs(-56) == 56); assert(abs(2321312L) == 2321312L); - assert(abs(-1+1i) == sqrt(2.0)); + assert(mfeq(abs(-1+1i), sqrt(2.0), .0000001)); } /*********************************** @@ -186,6 +201,7 @@ unittest * Results are undefined if |x| >= $(POWER 2,64). */ +version(GNU) alias gcc.config.cosl cos; else real cos(real x); /* intrinsic */ /*********************************** @@ -201,6 +217,7 @@ real cos(real x); /* intrinsic */ * Results are undefined if |x| >= $(POWER 2,64). */ +version(GNU) alias gcc.config.sinl sin; else real sin(real x); /* intrinsic */ @@ -215,6 +232,7 @@ real sin(real x); /* intrinsic */ * ) */ +version(GNU) alias gcc.config.tanl tan; else real tan(real x) { asm @@ -290,6 +308,12 @@ unittest for (i = 0; i < vals.length; i++) { + /* Library tanl does not have the same limit as the fptan + instruction. */ + version (GNU) + if (i == vals.length - 1) + continue; + real x = vals[i][0]; real r = vals[i][1]; real t = tan(x); @@ -490,7 +514,7 @@ unittest real atanh(real x) { // log( (1+x)/(1-x) ) == log ( 1 + (2*x)/(1-x) ) - return 0.5 * log1p( 2 * x / (1 - x) ); + return copysign(0.5 * log1p( 2 * x / (1 - x) ), x); } unittest @@ -529,8 +553,11 @@ extern (C) real rndtonl(real x); * ) */ +version(GNU) float sqrt(float x) { return gcc.config.sqrtf(x); } else float sqrt(float x); /* intrinsic */ +version(GNU) double sqrt(double x) { return gcc.config.sqrt(x); } else /// ditto double sqrt(double x); /* intrinsic */ /// ditto +version(GNU) real sqrt(real x) { return gcc.config.sqrtl(x); } else /// ditto real sqrt(real x); /* intrinsic */ /// ditto creal sqrt(creal z) @@ -593,6 +620,7 @@ real exp(real x) { return std.c.math.ex * -∞ +0.0 * ) */ +version (GNU_Need_exp2_log2) real exp2(real x) { return std.c.math.powl(2, x); } else real exp2(real x) { return std.c.math.exp2l(x); } /****************************************** @@ -610,6 +638,7 @@ real exp2(real x) { return std.c.math.e * ) */ +version (GNU_msvcrt_math) { /* nothing */ } else real expm1(real x) { return std.c.math.expm1l(x); } @@ -634,6 +663,8 @@ real expm1(real x) { return std.c.math. real frexp(real value, out int exp) { + version (X86) { + ushort* vu = cast(ushort*)&value; long* vl = cast(long*)&value; uint ex; @@ -681,6 +712,23 @@ real frexp(real value, out int exp) vu[4] = cast(ushort)((0x8000 & vu[4]) | 0x3FFE); } return value; + + } + else version(GNU) + { + switch (gcc.config.fpclassify(value)) { + case gcc.config.FP_NORMAL: + case gcc.config.FP_ZERO: + case gcc.config.FP_SUBNORMAL: // I can only hope the library frexp normalizes the value... + return gcc.config.frexpl(value, & exp); + case gcc.config.FP_INFINITE: + exp = gcc.config.signbit(value) ? int.min : int.max; + return value; + case gcc.config.FP_NAN: + exp = int.min; + return value; + } + } } @@ -711,6 +759,8 @@ unittest for (i = 0; i < vals.length; i++) { + if (i >= 6 && i <= 8 && real.min_exp > -16381) + continue; real x = vals[i][0]; real e = vals[i][1]; int exp = cast(int)vals[i][2]; @@ -748,6 +798,7 @@ alias std.c.math.FP_ILOGBNAN FP_ILOGBNAN * References: frexp */ +version(GNU) alias gcc.config.ldexpl ldexp; else real ldexp(real n, int exp); /* intrinsic */ /************************************** @@ -804,6 +855,7 @@ real log1p(real x) { return std.c.math. * +∞ +∞ no no * ) */ +version (GNU_Need_exp2_log2) real log2(real x) { return std.c.math.logl(x) / LOG2; } else real log2(real x) { return std.c.math.log2l(x); } /***************************************** @@ -882,6 +934,7 @@ real cbrt(real x) { return std.c.math.c * ±∞ +∞ * ) */ +version (GNU) alias gcc.config.fabsl fabs; else real fabs(real x); /* intrinsic */ @@ -993,6 +1046,9 @@ unittest for (i = 0; i < vals.length; i++) { + if (i == 5 && real.max_exp < 16383) + continue; + real x = vals[i][0]; real y = vals[i][1]; real z = vals[i][2]; @@ -1010,6 +1066,7 @@ unittest * * error function */ +version (GNU_msvcrt_math) { /* nothing */ } else real erf(real x) { return std.c.math.erfl(x); } /********************************** @@ -1017,6 +1074,7 @@ real erf(real x) { return std.c.math.er * * complementary error function */ +version (GNU_msvcrt_math) { /* nothing */ } else real erfc(real x) { return std.c.math.erfcl(x); } /*********************************** @@ -1067,6 +1125,12 @@ real lgamma(real x) * $(LINK http://www.netlib.org/cephes/ldoubdoc.html#gamma) */ /* Documentation prepared by Don Clugston */ +version (GNU_Need_tgamma) +{ + private import etc.gamma; + alias etc.gamma.tgamma tgamma; +} +else real tgamma(real x) { return std.c.math.tgammal(x); @@ -1093,6 +1157,11 @@ real floor(real x) { return std.c.math. * Unlike the rint functions, nearbyint does not raise the * FE_INEXACT exception. */ +version (GNU_Need_nearbyint) +{ + // not implemented yet +} +else real nearbyint(real x) { return std.c.math.nearbyintl(x); } /********************************** @@ -1103,6 +1172,7 @@ real nearbyint(real x) { return std.c.ma * nearbyint performs * the same operation, but does not set the FE_INEXACT exception. */ +version(GNU) alias gcc.config.rintl rint; else real rint(real x); /* intrinsic */ /*************************************** @@ -1122,6 +1192,38 @@ long lrint(real x) * If the fractional part of x is exactly 0.5, the return value is rounded to * the even integer. */ +version (GNU_Need_round) +{ + real round(real x) + { + real y = floor(x); + real r = x - y; + if (r > 0.5) + return y + 1; + else if (r == 0.5) + { + r = y - 2.0 * floor(0.5 * y); + if (r == 1.0) + return y + 1; + } + return y; + } + unittest { + real r; + assert(isnan(round(real.nan))); + r = round(real.infinity); + assert(isinf(r) && r > 0); + r = round(-real.infinity); + assert(isinf(r) && r < 0); + assert(round(3.4) == 3); + assert(round(3.5) == 4); + assert(round(3.6) == 4); + assert(round(-3.4) == -3); + assert(round(-3.5) == -4); + assert(round(-3.6) == -4); + } +} +else real round(real x) { return std.c.math.roundl(x); } /********************************************** @@ -1143,6 +1245,24 @@ long lround(real x) * * This is also known as "chop" rounding. */ +version (GNU_Need_trunc) +{ + real trunc(real n) { return n >= 0 ? std.math.floor(n) : std.math.ceil(n); } + unittest + { + real r; + r = trunc(real.infinity); + assert(isinf(r) && r > 0); + r = trunc(-real.infinity); + assert(isinf(r) && r < 0); + assert(isnan(trunc(real.nan))); + assert(trunc(3.3) == 3); + assert(trunc(3.6) == 3); + assert(trunc(-3.3) == -3); + assert(trunc(-3.6) == -3); + } +} +else real trunc(real x) { return std.c.math.truncl(x); } /**************************************************** @@ -1179,6 +1299,7 @@ real remquo(real x, real y, out int n) / * Returns !=0 if e is a NaN. */ +version (X86) int isnan(real e) { ushort* pe = cast(ushort *)&e; @@ -1187,6 +1308,8 @@ int isnan(real e) return (pe[4] & 0x7FFF) == 0x7FFF && *ps & 0x7FFFFFFFFFFFFFFF; } +else version(GNU) + alias gcc.config.isnan isnan; unittest { @@ -1202,12 +1325,15 @@ unittest * Returns !=0 if e is finite. */ +version (X86) int isfinite(real e) { ushort* pe = cast(ushort *)&e; return (pe[4] & 0x7FFF) != 0x7FFF; } +else version(GNU) + alias gcc.config.isfinite isfinite; unittest { @@ -1225,6 +1351,7 @@ unittest * be converted to normal reals. */ +version (X86) int isnormal(float x) { uint *p = cast(uint *)&x; @@ -1234,9 +1361,12 @@ int isnormal(float x) //printf("e = x%x, *p = x%x\n", e, *p); return e && e != 0x7F800000; } +else version(GNU) + alias gcc.config.isnormal isnormal; /// ditto +version (X86) int isnormal(double d) { uint *p = cast(uint *)&d; @@ -1245,9 +1375,11 @@ int isnormal(double d) e = p[1] & 0x7FF00000; return e && e != 0x7FF00000; } +else version(GNU) { /* nothing, handled above */ } /// ditto +version (X86) int isnormal(real e) { ushort* pe = cast(ushort *)&e; @@ -1255,6 +1387,7 @@ int isnormal(real e) return (pe[4] & 0x7FFF) != 0x7FFF && *ps < 0; } +else version(GNU) { /* nothing, handled above */ } unittest { @@ -1276,6 +1409,7 @@ unittest * be converted to normal reals. */ +version (X86) int issubnormal(float f) { uint *p = cast(uint *)&f; @@ -1283,6 +1417,8 @@ int issubnormal(float f) //printf("*p = x%x\n", *p); return (*p & 0x7F800000) == 0 && *p & 0x007FFFFF; } +else version(GNU) + alias gcc.config.issubnormal issubnormal; unittest { @@ -1294,12 +1430,14 @@ unittest /// ditto +version (X86) int issubnormal(double d) { uint *p = cast(uint *)&d; return (p[1] & 0x7FF00000) == 0 && (p[0] || p[1] & 0x000FFFFF); } +else version(GNU) { /* nothing, handled above */ } unittest { @@ -1311,6 +1449,7 @@ unittest /// ditto +version (X86) int issubnormal(real e) { ushort* pe = cast(ushort *)&e; @@ -1318,6 +1457,7 @@ int issubnormal(real e) return (pe[4] & 0x7FFF) == 0 && *ps > 0; } +else version(GNU) { /* nothing, handled above */ } unittest { @@ -1331,6 +1471,7 @@ unittest * Return !=0 if e is ±∞. */ +version (X86) int isinf(real e) { ushort* pe = cast(ushort *)&e; @@ -1339,7 +1480,9 @@ int isinf(real e) return (pe[4] & 0x7FFF) == 0x7FFF && *ps == 0x8000000000000000; } - +else version (GNU) + alias gcc.config.isinf isinf; + unittest { assert(isinf(float.infinity)); @@ -1354,6 +1497,7 @@ unittest * Return 1 if sign bit of e is set, 0 if not. */ +version (X86) int signbit(real e) { ubyte* pe = cast(ubyte *)&e; @@ -1361,6 +1505,8 @@ int signbit(real e) //printf("e = %Lg\n", e); return (pe[9] & 0x80) != 0; } +else version (GNU) + alias gcc.config.signbit signbit; unittest { @@ -1377,6 +1523,7 @@ unittest * Return a value composed of to with from's sign bit. */ +version (X86) real copysign(real to, real from) { ubyte* pto = cast(ubyte *)&to; @@ -1387,6 +1534,8 @@ real copysign(real to, real from) return to; } +else version (GNU) + alias gcc.config.copysignl copysign; unittest { @@ -1411,6 +1560,9 @@ unittest /****************************************** * Creates a quiet NAN with the information from tagp[] embedded in it. */ +version (GNU_Need_nan) +real nan(char[] tagp) { return real.nan; } // could implement with strtod, but need test if THAT works first +else real nan(char[] tagp) { return std.c.math.nanl(toStringz(tagp)); } /****************************************** @@ -1554,7 +1706,8 @@ real pow(real x, int n) real pow(real x, real y) { - version (linux) // C pow() often does not handle special values correctly + //version (linux) // C pow() often does not handle special values correctly + version (GNU) // ...assume the same for all GCC targets { if (isnan(y)) return y; @@ -1689,6 +1842,10 @@ bool isNegZero(real x) return (x == 0) && signbit(x); } +version (X86) +{ +// These routines assume Intel 80-bit floating point format + /************************************** * To what precision is x equal to y? * @@ -1788,7 +1945,22 @@ unittest assert(feqrel(real.max,-real.max)==0); } +} // version(X86) +else +{ + // not implemented +} + + +// The space allocated for real varies across targets. +version (D_InlineAsm_X86) +{ + static if (real.sizeof == 10) + { version = poly_10; } + else static if (real.sizeof == 12) + { version = poly_12; } +} /*********************************** * Evaluate polynomial A(x) = a0 + a1x + a2x² + a3x³ ... * @@ -1803,63 +1975,60 @@ in } body { - version (D_InlineAsm_X86) + version (poly_10) { - version (Windows) + asm // assembler by W. Bright { - asm // assembler by W. Bright - { - // EDX = (A.length - 1) * real.sizeof - mov ECX,A[EBP] ; // ECX = A.length - dec ECX ; - lea EDX,[ECX][ECX*8] ; - add EDX,ECX ; - add EDX,A+4[EBP] ; - fld real ptr [EDX] ; // ST0 = coeff[ECX] - jecxz return_ST ; - fld x[EBP] ; // ST0 = x - fxch ST(1) ; // ST1 = x, ST0 = r - align 4 ; - L2: fmul ST,ST(1) ; // r *= x - fld real ptr -10[EDX] ; - sub EDX,10 ; // deg-- - faddp ST(1),ST ; - dec ECX ; - jne L2 ; - fxch ST(1) ; // ST1 = r, ST0 = x - fstp ST(0) ; // dump x - align 4 ; - return_ST: ; - ; - } + // EDX = (A.length - 1) * real.sizeof + mov ECX,A[EBP] ; // ECX = A.length + dec ECX ; + lea EDX,[ECX][ECX*8] ; + add EDX,ECX ; + add EDX,A+4[EBP] ; + fld real ptr [EDX] ; // ST0 = coeff[ECX] + jecxz return_ST ; + fld x[EBP] ; // ST0 = x + fxch ST(1) ; // ST1 = x, ST0 = r + align 4 ; + L2: fmul ST,ST(1) ; // r *= x + fld real ptr -10[EDX] ; + sub EDX,10 ; // deg-- + faddp ST(1),ST ; + dec ECX ; + jne L2 ; + fxch ST(1) ; // ST1 = r, ST0 = x + fstp ST(0) ; // dump x + align 4 ; + return_ST: ; + ; } - else + } + else version (poly_12) + { + asm // above code with modifications for GCC { - asm // assembler by W. Bright - { - // EDX = (A.length - 1) * real.sizeof - mov ECX,A[EBP] ; // ECX = A.length - dec ECX ; - lea EDX,[ECX*8] ; - lea EDX,[EDX][ECX*4] ; - add EDX,A+4[EBP] ; - fld real ptr [EDX] ; // ST0 = coeff[ECX] - jecxz return_ST ; - fld x[EBP] ; // ST0 = x - fxch ST(1) ; // ST1 = x, ST0 = r - align 4 ; - L2: fmul ST,ST(1) ; // r *= x - fld real ptr -12[EDX] ; - sub EDX,12 ; // deg-- - faddp ST(1),ST ; - dec ECX ; - jne L2 ; - fxch ST(1) ; // ST1 = r, ST0 = x - fstp ST(0) ; // dump x - align 4 ; - return_ST: ; - ; - } + // EDX = (A.length - 1) * real.sizeof + mov ECX,A[EBP] ; // ECX = A.length + dec ECX ; + lea EDX,[ECX][ECX*2] ; + lea EDX,[EDX*4] ; + add EDX,A+4[EBP] ; + fld real ptr [EDX] ; // ST0 = coeff[ECX] + jecxz return_ST ; + fld x ; // ST0 = x + fxch ST(1) ; // ST1 = x, ST0 = r + align 4 ; + L2: fmul ST,ST(1) ; // r *= x + fld real ptr -12[EDX] ; + sub EDX,12 ; // deg-- + faddp ST(1),ST ; + dec ECX ; + jne L2 ; + fxch ST(1) ; // ST1 = r, ST0 = x + fstp ST(0) ; // dump x + align 4 ; + return_ST: ; + ; } } else diff -uNrp dmd-1.004/src/phobos/std/md5.d gdc-0.22/d/phobos/std/md5.d --- dmd-1.004/src/phobos/std/md5.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/md5.d 2006-12-17 06:03:04.000000000 +0100 @@ -89,12 +89,22 @@ These notices must be retained in any co documentation and/or software. */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + module std.md5; //debug=md5; // uncomment to turn on debugging printf's import std.string; +version(D_InlineAsm) + version(X86) + version = Asm86; + /*************************************** * Computes MD5 digest of array of data. */ @@ -170,14 +180,28 @@ struct MD5_CTX */ static uint ROTATE_LEFT(uint x, uint n) { - version (X86) + version (Asm86) { - asm - { naked ; - mov ECX,EAX ; - mov EAX,4[ESP] ; - rol EAX,CL ; - ret 4 ; + version (GNU) + { + asm + { + naked ; + mov ECX, n ; + mov EAX, x ; + rol EAX, CL ; + ret ; + } + } + else + { + asm + { naked ; + mov ECX,EAX ; + mov EAX,4[ESP] ; + rol EAX,CL ; + ret 4 ; + } } } else diff -uNrp dmd-1.004/src/phobos/std/mmfile.d gdc-0.22/d/phobos/std/mmfile.d --- dmd-1.004/src/phobos/std/mmfile.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/mmfile.d 2006-12-17 06:03:04.000000000 +0100 @@ -10,6 +10,12 @@ * WIKI=Phobos/StdMmfile */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + module std.mmfile; private import std.file; @@ -31,14 +37,30 @@ version (Win32) { // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getversion.asp dwVersion = GetVersion(); } + + private const bool Have_MMFile = true; // private for now... } -else version (linux) +else version (Unix) { - private import std.c.linux.linux; + version (GNU_Unix_Have_MMap) + { + private import std.c.unix.unix; + alias std.c.unix.unix unix; + + version = unix_mm; + private const bool Have_MMFile = true; + } + else + { + private const bool Have_MMFile = false; + } + } else { - static assert(0); + private const bool Have_MMFile = false; + // Can't simply fail because std.stream imports this module. + //static assert(0); } /** @@ -208,7 +230,7 @@ class MmFile errNo(); } - else version (linux) + else version (unix_mm) { char* namez = toStringz(filename); void* p; @@ -254,26 +276,26 @@ class MmFile { struct_stat statbuf; - fd = std.c.linux.linux.open(namez, oflag, fmode); + fd = unix.open(namez, oflag, fmode); if (fd == -1) { // printf("\topen error, errno = %d\n",getErrno()); errNo(); } - if (std.c.linux.linux.fstat(fd, &statbuf)) + if (unix.fstat(fd, &statbuf)) { //printf("\tfstat error, errno = %d\n",getErrno()); - std.c.linux.linux.close(fd); + unix.close(fd); errNo(); } if (prot & PROT_WRITE && size > statbuf.st_size) { // Need to make the file size bytes big - std.c.linux.linux.lseek(fd, cast(int)(size - 1), SEEK_SET); + unix.lseek(fd, cast(off_t)(size - 1), SEEK_SET); char c = 0; - std.c.linux.linux.write(fd, &c, 1); + unix.write(fd, &c, 1); } else if (prot & PROT_READ && size == 0) size = statbuf.st_size; @@ -288,12 +310,16 @@ class MmFile p = mmap(address, initial_map, prot, flags, fd, 0); if (p == MAP_FAILED) { if (fd != -1) - std.c.linux.linux.close(fd); + unix.close(fd); errNo(); } data = p[0 .. initial_map]; } + else static if (! Have_MMFile) + { + throw new FileException("This system does support memory mapped files"); + } else { static assert(0); @@ -317,12 +343,15 @@ class MmFile errNo(); hFile = INVALID_HANDLE_VALUE; } - else version (linux) + else version (unix_mm) { - if (fd != -1 && std.c.linux.linux.close(fd) == -1) + if (fd != -1 && unix.close(fd) == -1) errNo(); fd = -1; } + else static if (! Have_MMFile) + { + } else { static assert(0); @@ -339,7 +368,7 @@ class MmFile { FlushViewOfFile(data.ptr, data.length); } - else version (linux) + else version (unix_mm) { int i; @@ -347,6 +376,9 @@ class MmFile if (i != 0) errNo(); } + else static if (! Have_MMFile) + { + } else { static assert(0); @@ -434,7 +466,7 @@ class MmFile if (data && UnmapViewOfFile(data.ptr) == FALSE && (dwVersion & 0x80000000) == 0) errNo(); - } else { + } else version (unix_mm) { if (data && munmap(cast(void*)data, data.length) != 0) errNo(); } @@ -452,8 +484,8 @@ class MmFile uint hi = cast(uint)(start>>32); p = MapViewOfFileEx(hFileMap, dwDesiredAccess, hi, cast(uint)start, len, address); if (!p) errNo(); - } else { - p = mmap(address, len, prot, flags, fd, cast(int)start); + } else version (unix_mm) { + p = mmap(address, len, prot, flags, fd, cast(off_t)start); if (p == MAP_FAILED) errNo(); } data = p[0 .. len]; @@ -513,13 +545,16 @@ class MmFile HANDLE hFileMap = null; uint dwDesiredAccess; } - else version (linux) + else version (unix_mm) { int fd; int prot; int flags; int fmode; } + else static if (! Have_MMFile) + { + } else { static assert(0); @@ -532,10 +567,14 @@ class MmFile { throw new FileException(filename, GetLastError()); } - else version (linux) + else version (Unix) { throw new FileException(filename, getErrno()); } + else static if (! Have_MMFile) + { + throw new FileException(filename, "MMFile unsupported"); + } else { static assert(0); @@ -544,6 +583,8 @@ class MmFile } unittest { + static if (Have_MMFile) + { const size_t K = 1024; size_t win = 64*K; // assume the page size is 64K version(Win32) { @@ -552,7 +593,7 @@ unittest { GetSystemInfo(&sysinfo); win = sysinfo.dwAllocationGranularity; +/ - } else version (linux) { + } else version (Unix) { // getpagesize() is not defined in the unix D headers so use the guess } MmFile mf = new MmFile("testing.txt",MmFile.Mode.ReadWriteNew,100*K,null,win); @@ -572,4 +613,5 @@ unittest { assert( data2[length-1] == 'b' ); delete mf; std.file.remove("testing.txt"); + } } diff -uNrp dmd-1.004/src/phobos/std/moduleinit.d gdc-0.22/d/phobos/std/moduleinit.d --- dmd-1.004/src/phobos/std/moduleinit.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/moduleinit.d 2006-07-03 16:46:40.000000000 +0200 @@ -1,4 +1,10 @@ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + module std.moduleinit; //debug = 1; @@ -44,8 +50,16 @@ class ModuleCtorError : Exception // linux: this gets initialized in _moduleCtor() extern (C) ModuleInfo[] _moduleinfo_array; +version (GNU) +{ + version = ModRefStyle; +} version (linux) { + version = ModRefStyle; +} +version (ModRefStyle) +{ // This linked list is created by a compiler generated function inserted // into the .ctor list by the compiler. struct ModuleReference @@ -70,7 +84,7 @@ extern (C) int _fatexit(void *); extern (C) void _moduleCtor() { debug printf("_moduleCtor()\n"); - version (linux) + version (ModRefStyle) { int len = 0; ModuleReference *mr; diff -uNrp dmd-1.004/src/phobos/std/outbuffer.d gdc-0.22/d/phobos/std/outbuffer.d --- dmd-1.004/src/phobos/std/outbuffer.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/outbuffer.d 2007-02-03 17:34:12.000000000 +0100 @@ -14,6 +14,12 @@ // Written by Walter Bright +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + module std.outbuffer; private @@ -245,23 +251,35 @@ class OutBuffer char* f; uint psize; int count; + va_list args_copy; f = toStringz(format); p = buffer.ptr; psize = buffer.length; for (;;) { + va_copy(args_copy, args); version(Win32) { - count = _vsnprintf(p,psize,f,args); + count = _vsnprintf(p,psize,f,args_copy); if (count != -1) break; psize *= 2; p = cast(char *) alloca(psize); // buffer too small, try again with larger size } - version(linux) + else version(GNU) { + count = vsnprintf(p,psize,f,args_copy); + if (count == -1) + psize *= 2; + else if (count >= psize) + psize = count + 1; + else + break; + p = cast(char *) alloca(psize); // buffer too small, try again with larger size + } + else version(linux) { - count = vsnprintf(p,psize,f,args); + count = vsnprintf(p,psize,f,args_copy); if (count == -1) psize *= 2; else if (count >= psize) @@ -292,10 +310,17 @@ class OutBuffer void printf(char[] format, ...) { - va_list ap; - ap = cast(va_list)&format; - ap += format.sizeof; - vprintf(format, ap); + version (GNU) + { + vprintf(format, _argptr); + } + else + { + va_list ap; + ap = cast(va_list)&format; + ap += format.sizeof; + vprintf(format, ap); + } } /***************************************** diff -uNrp dmd-1.004/src/phobos/std/path.d gdc-0.22/d/phobos/std/path.d --- dmd-1.004/src/phobos/std/path.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/path.d 2006-12-17 06:03:04.000000000 +0100 @@ -16,6 +16,12 @@ * use the std.file module first (i.e. std.file.isDir()). */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, March 2006 +*/ + module std.path; //debug=path; // uncomment to turn on debugging printf's @@ -23,10 +29,10 @@ module std.path; private import std.string; -version(linux) +version(Unix) { private import std.c.stdlib; - private import std.c.linux.linux; + private import std.c.unix.unix; private import std.outofmemory; } @@ -48,7 +54,7 @@ version(Windows) const char[1] curdir = "."; /// String representing the current directory. const char[2] pardir = ".."; /// String representing the parent directory. } -version(linux) +else version(Unix) { /** String used to separate directory names in a path. Under * Windows this is a backslash, under Linux a slash. */ @@ -65,6 +71,10 @@ version(linux) const char[1] curdir = "."; /// String representing the current directory. const char[2] pardir = ".."; /// String representing the parent directory. } +else +{ + static assert(0); +} /***************************** * Compare file names. @@ -78,7 +88,7 @@ version(linux) version (Windows) alias std.string.cmp fcmp; -version (linux) alias std.string.icmp fcmp; +version (Unix) alias std.string.icmp fcmp; /************************** * Extracts the extension from a filename or path. @@ -125,7 +135,7 @@ char[] getExt(char[] fullname) if (fullname[i] == ':' || fullname[i] == '\\') break; } - version(linux) + else version(Unix) { if (fullname[i] == '/') break; @@ -142,28 +152,28 @@ unittest version (Win32) result = getExt("d:\\path\\foo.bat"); - version (linux) + version (Unix) result = getExt("/path/foo.bat"); i = cmp(result, "bat"); assert(i == 0); version (Win32) result = getExt("d:\\path\\foo."); - version (linux) + version (Unix) result = getExt("d/path/foo."); i = cmp(result, ""); assert(i == 0); version (Win32) result = getExt("d:\\path\\foo"); - version (linux) + version (Unix) result = getExt("d/path/foo"); i = cmp(result, ""); assert(i == 0); version (Win32) result = getExt("d:\\path.bar\\foo"); - version (linux) + version (Unix) result = getExt("/path.bar/foo"); i = cmp(result, ""); @@ -219,7 +229,7 @@ char[] getName(char[] fullname) if (fullname[i] == ':' || fullname[i] == '\\') break; } - version(linux) + version(Unix) { if (fullname[i] == '/') break; @@ -288,7 +298,7 @@ char[] getBaseName(char[] fullname) if (fullname[i - 1] == ':' || fullname[i - 1] == '\\') break; } - version(linux) + else version(Unix) { if (fullname[i - 1] == '/') break; @@ -305,7 +315,7 @@ unittest version (Windows) result = getBaseName("d:\\path\\foo.bat"); - version (linux) + version (Unix) result = getBaseName("/path/foo.bat"); //printf("result = '%.*s'\n", result); i = cmp(result, "foo.bat"); @@ -313,7 +323,7 @@ unittest version (Windows) result = getBaseName("a\\b"); - version (linux) + version (Unix) result = getBaseName("a/b"); i = cmp(result, "b"); assert(i == 0); @@ -371,7 +381,7 @@ char[] getDirName(char[] fullname) break; } } - version(linux) + else version(Unix) { if (fullname[i - 1] == '/') { i--; @@ -419,7 +429,7 @@ char[] getDrive(char[] fullname) } return null; } - version(linux) + else version(Unix) { return null; } @@ -629,7 +639,7 @@ char[] join(char[] p1, char[] p2) } } } - version(linux) + else version(Unix) { if (p2[0] == sep[0]) { @@ -657,7 +667,7 @@ unittest p = join("foo", "bar"); version (Win32) i = cmp(p, "foo\\bar"); - version (linux) + version (Unix) i = cmp(p, "foo/bar"); assert(i == 0); @@ -665,7 +675,7 @@ unittest { p = join("foo\\", "bar"); i = cmp(p, "foo\\bar"); } - version (linux) + version (Unix) { p = join("foo/", "bar"); i = cmp(p, "foo/bar"); } @@ -675,7 +685,7 @@ unittest { p = join("foo", "\\bar"); i = cmp(p, "\\bar"); } - version (linux) + version (Unix) { p = join("foo", "/bar"); i = cmp(p, "/bar"); } @@ -685,7 +695,7 @@ unittest { p = join("foo\\", "\\bar"); i = cmp(p, "\\bar"); } - version (linux) + version (Unix) { p = join("foo/", "/bar"); i = cmp(p, "/bar"); } @@ -767,10 +777,17 @@ int fncharmatch(dchar c1, dchar c2) } return true; } - version (linux) + else version (Unix) { return c1 == c2; } + /* this is filesystem-dependent, figure out the filesystem? + else version (GNU) + { + // %% figure out filesystem? + return c1 == c2; + } + */ } /************************************ @@ -929,7 +946,7 @@ unittest version (Win32) assert(fnmatch("foo", "Foo")); - version (linux) + version (Unix) assert(!fnmatch("foo", "Foo")); assert(fnmatch("foo", "*")); assert(fnmatch("foo.bar", "*")); @@ -1011,7 +1028,7 @@ unittest char[] expandTilde(char[] inputPath) { - version(linux) + version(Unix) { static assert(sep.length == 1); @@ -1040,7 +1057,7 @@ unittest { debug(path) printf("path.expandTilde.unittest\n"); - version (linux) + version (Unix) { // Retrieve the current home variable. char* c_home = getenv("HOME"); @@ -1069,13 +1086,15 @@ unittest unsetenv("HOME"); // Test user expansion for root. Are there unices without /root? + /* assert(expandTilde("~root") == "/root"); assert(expandTilde("~root/") == "/root/"); + */ assert(expandTilde("~Idontexist/hey") == "~Idontexist/hey"); } } -version (linux) +version (Unix) { /** @@ -1149,6 +1168,9 @@ private char[] expandFromDatabase(char[] } assert(last_char > 1); + version (GNU_Unix_Have_getpwnam_r) + { + // Reserve C memory for the getpwnam_r() function. passwd result; int extra_memory_size = 5 * 1024; @@ -1163,7 +1185,7 @@ private char[] expandFromDatabase(char[] // Obtain info from database. passwd *verify; std.c.stdlib.setErrno(0); - if (getpwnam_r(username.ptr, &result, extra_memory, extra_memory_size, + if (getpwnam_r(username.ptr, &result, cast(char*) extra_memory, extra_memory_size, &verify) == 0) { // Failure if verify doesn't point at result. @@ -1173,8 +1195,19 @@ private char[] expandFromDatabase(char[] break; } - if (std.c.stdlib.getErrno() != ERANGE) + switch (std.c.stdlib.getErrno()) { + case 0: + case ENOENT: + case ESRCH: + case EBADF: + case EPERM: + goto Lnotfound; + case ERANGE: + break; + default: + // not just out of memory: EMFILE, ENFILE too goto Lerror; + } // extra_memory isn't large enough std.c.stdlib.free(extra_memory); @@ -1193,6 +1226,22 @@ Lerror: std.c.stdlib.free(extra_memory); _d_OutOfMemory(); return null; + + } + else + { + passwd * result; + + /* This does not guarantee another thread will not + use getpwnam at the same time */ + synchronized { + result = getpwnam(username); + } + + if (result) + path = combineCPathWithDPath(result.pw_dir, path, last_char); + return path; + } } } diff -uNrp dmd-1.004/src/phobos/std/perf.d gdc-0.22/d/phobos/std/perf.d --- dmd-1.004/src/phobos/std/perf.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/perf.d 2006-06-02 05:31:29.000000000 +0200 @@ -21,6 +21,12 @@ * * ////////////////////////////////////////////////////////////////////////// */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + /** \file std/perf.d This file contains platform-independent performance classes */ @@ -84,22 +90,27 @@ auto class PerformanceCounterScope(T) this(PerformanceCounterScope rhs); } -version(linux) +version(Unix) { - extern (C) - { - private struct timeval + version (GNU) { + private import std.c.unix.unix; + } + else version (linux) { + extern (C) { - int tv_sec; /*!< The number of seconds, since Jan. 1, 1970, in the time value. */ - int tv_usec; /*!< The number of microseconds in the time value. */ - }; - private struct timezone - { - int tz_minuteswest; /*!< minutes west of Greenwich. */ - int tz_dsttime; /*!< type of dst corrections to apply. */ - }; - private void gettimeofday(timeval *tv, timezone *tz); + private struct timeval + { + int tv_sec; /*!< The number of seconds, since Jan. 1, 1970, in the time value. */ + int tv_usec; /*!< The number of microseconds in the time value. */ + }; + private struct timezone + { + int tz_minuteswest; /*!< minutes west of Greenwich. */ + int tz_dsttime; /*!< type of dst corrections to apply. */ + }; + private void gettimeofday(timeval *tv, timezone *tz); + } } /* ////////////////////////////////////////////////////////////////////////// */ diff -uNrp dmd-1.004/src/phobos/std/process.d gdc-0.22/d/phobos/std/process.d --- dmd-1.004/src/phobos/std/process.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/process.d 2006-06-02 05:31:29.000000000 +0200 @@ -24,12 +24,18 @@ * o This notice may not be removed or altered from any source * distribution. */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, October 2004 +*/ /** * Macros: * WIKI=Phobos/StdProcess */ + module std.process; private import std.c.stdlib; @@ -83,7 +89,7 @@ int spawnvp(int mode, char[] pathname, c toAStringz(argv, argv_); - version(linux) + version(Unix) { return _spawnvp(mode, toStringz(pathname), argv_); } @@ -93,9 +99,9 @@ int spawnvp(int mode, char[] pathname, c } } -version(linux) +version(Unix) { -private import std.c.linux.linux; +private import std.c.unix.unix; int _spawnvp(int mode, char *pathname, char **argv) { int retval = 0; @@ -195,7 +201,7 @@ int execvp(char[] pathname, char[][] arg /** ditto */ int execvpe(char[] pathname, char[][] argv, char[][] envp) { -version(linux) +version (GNU_Need_execvpe) { // Is pathname rooted? if(pathname[0] == '/') diff -uNrp dmd-1.004/src/phobos/std/random.d gdc-0.22/d/phobos/std/random.d --- dmd-1.004/src/phobos/std/random.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/random.d 2007-02-03 17:34:12.000000000 +0100 @@ -6,6 +6,12 @@ // random.d // www.digitalmars.com +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + module std.random; // Segments of the code in this file Copyright (c) 1997 by Rick Booth @@ -16,7 +22,11 @@ version (Win32) extern(Windows) int QueryPerformanceCounter(ulong *count); } -version (linux) +else version (GNU) +{ + private import std.c.unix.unix; +} +else version (linux) { private import std.c.linux.linux; } @@ -98,7 +108,7 @@ static this() { QueryPerformanceCounter(&s); } - version(linux) + else version(Unix) { // time.h // sys/time.h diff -uNrp dmd-1.004/src/phobos/std/regexp.d gdc-0.22/d/phobos/std/regexp.d --- dmd-1.004/src/phobos/std/regexp.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/regexp.d 2007-02-03 18:35:36.000000000 +0100 @@ -23,6 +23,12 @@ * distribution. */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + /********************************************** * $(LINK2 http://www.digitalmars.com/ctg/regular.html, Regular expressions) * are a powerful method of string pattern matching. @@ -141,6 +147,7 @@ private import std.outbuffer; import std.bitarray; import std.utf; + import std.intrinsic; } /** Regular expression to extract an _email address */ @@ -1585,7 +1592,7 @@ int trymatch(int pc, int pcend) c1 = input[src]; //printf("[x%02x]=x%02x, x%02x\n", c1 >> 3, ((&program[pc + 1 + 4])[c1 >> 3] ), (1 << (c1 & 7))); if (c1 <= pu[0] && - !((&(program[pc + 1 + 4]))[c1 >> 3] & (1 << (c1 & 7)))) + !bt(cast(uint*)&(program[pc + 1 + 4]), c1)) // assumes BitArray implementation goto Lnomatch; pc += 1 + 2 * ushort.sizeof + len; break; @@ -1600,7 +1607,7 @@ int trymatch(int pc, int pcend) c1 = input[src]; if (c1 > pu[0]) goto Lnomatch; - if (!((&program[pc + 1 + 4])[c1 >> 3] & (1 << (c1 & 7)))) + if (!bt(cast(uint*)&(program[pc + 1 + 4]), c1)) // assumes BitArray implementation goto Lnomatch; src++; pc += 1 + 2 * ushort.sizeof + len; @@ -1615,7 +1622,7 @@ int trymatch(int pc, int pcend) len = pu[1]; c1 = input[src]; if (c1 <= pu[0] && - ((&program[pc + 1 + 4])[c1 >> 3] & (1 << (c1 & 7)))) + bt(cast(uint*)&(program[pc + 1 + 4]), c1)) // assumes BitArray implementation goto Lnomatch; src++; pc += 1 + 2 * ushort.sizeof + len; @@ -2349,12 +2356,20 @@ class Range { uint u2; u2 = base ? base - &buf.data[0] : 0; - buf.fill0(b - maxb + 1); + ++b; + version (BigEndian) + { + while (b & (uint.sizeof-1)) + ++b; + } + + buf.fill0(b - maxb); base = &buf.data[u2]; - maxb = b + 1; - //bits = (cast(bit*)this.base)[0 .. maxc + 1]; + maxb = b; + // %% moved array recreate out of this condition bits.ptr = cast(uint*)this.base; - } + } + //bits = (cast(bit*)this.base)[0 .. maxc + 1]; bits.len = maxc + 1; } } diff -uNrp dmd-1.004/src/phobos/std/socket.d gdc-0.22/d/phobos/std/socket.d --- dmd-1.004/src/phobos/std/socket.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/socket.d 2007-01-27 17:44:01.000000000 +0100 @@ -24,6 +24,12 @@ Thanks to Benjamin Herr for his assistance. */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, April 2005 +*/ + /** * Notes: For Win32 systems, link with ws2_32.lib. * Example: See /dmd/samples/d/listener.d. @@ -37,11 +43,19 @@ module std.socket; private import std.string, std.stdint, std.c.string, std.c.stdlib; -version(linux) +version(Unix) { version = BsdSockets; } +version (skyos) { /* nothging */ } +else +{ + version = have_getservbyport; + version = have_getprotobynumber; +} + + version(Win32) { private import std.c.windows.windows, std.c.windows.winsock; @@ -58,10 +72,10 @@ version(Win32) } else version(BsdSockets) { - version(linux) + version (Unix) { - private import std.c.linux.linux, std.c.linux.socket; - private alias std.c.linux.linux.timeval _ctimeval; + private import std.c.unix.unix; + private alias std.c.unix.unix.timeval _ctimeval; } typedef int32_t socket_t = -1; @@ -88,7 +102,7 @@ class SocketException: Exception { errorCode = err; - version(linux) + version(Unix) { if(errorCode > 0) { @@ -231,12 +245,17 @@ class Protocol // Same as getprotobynumber(). bool getProtocolByType(ProtocolType type) { + version (have_getprotobynumber) + { protoent* proto; proto = getprotobynumber(type); if(!proto) return false; populate(proto); return true; + } + else + return false; } } @@ -323,12 +342,17 @@ class Service /// ditto bool getServiceByPort(ushort port, char[] protocolName) { + version (have_getservbyport) + { servent* serv; serv = getservbyport(port, toStringz(protocolName)); if(!serv) return false; populate(serv); return true; + } + else + return false; } @@ -336,12 +360,17 @@ class Service /// ditto bool getServiceByPort(ushort port) { + version (have_getservbyport) + { servent* serv; serv = getservbyport(port, null); if(!serv) return false; populate(serv); return true; + } + else + return false; } } @@ -829,7 +858,14 @@ class SocketSet else version(BsdSockets) { maxfd = -1; - buf[0 .. nbytes] = 0; + version(GNU) + { + FD_ZERO(_fd_set); + } + else + { + buf[0 .. nbytes] = 0; + } } } @@ -844,7 +880,15 @@ class SocketSet } else version(BsdSockets) { - assert(FDELT(s) < nbytes / socket_t.sizeof); + version(GNU) + { + // Tries to account for little and big endian..er needs work + // assert((s/NFDBITS+1)*NFDBITS/8 <= nbytes); + } + else + { + assert(FDELT(s) < nbytes / socket_t.sizeof); + } } } body @@ -942,9 +986,16 @@ enum SocketOptionLevel: int IPV6 = ProtocolType.IPV6, /// internet protocol version 6 level } + /// Linger information for use with SocketOption.LINGER. extern(C) struct linger { + version (BsdSockets) + version (GNU) + { + private alias std.c.unix.unix.linger __unix_linger; + static assert(linger.sizeof == __unix_linger.sizeof); + } // D interface version(Win32) { @@ -953,8 +1004,18 @@ extern(C) struct linger } else version(BsdSockets) { - int32_t on; - int32_t time; + version (GNU) + { + + typeof(__unix_linger.l_onoff) on; + typeof(__unix_linger.l_linger) time; + + } + else + { + int32_t on; + int32_t time; + } } // C interface @@ -1145,7 +1206,7 @@ class Socket if(WSAEWOULDBLOCK == err) return; } - else version(linux) + else version(Unix) { if(EINPROGRESS == err) return; @@ -1483,12 +1544,12 @@ class Socket //make sure none of the SocketSet's are the same object if(checkRead) { - assert(checkRead !is checkWrite); - assert(checkRead !is checkError); + assert(checkRead !is checkWrite); + assert(checkRead !is checkError); } if(checkWrite) { - assert(checkWrite !is checkError); + assert(checkWrite !is checkError); } } body @@ -1549,7 +1610,7 @@ class Socket if(_SOCKET_ERROR == result && WSAGetLastError() == WSAEINTR) return -1; } - else version(linux) + else version(Unix) { if(_SOCKET_ERROR == result && getErrno() == EINTR) return -1; diff -uNrp dmd-1.004/src/phobos/std/stdarg.d gdc-0.22/d/phobos/std/stdarg.d --- dmd-1.004/src/phobos/std/stdarg.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/stdarg.d 2006-06-02 05:31:29.000000000 +0200 @@ -6,17 +6,38 @@ /* This is for use with variable argument lists with extern(D) linkage. */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + module std.stdarg; -alias void* va_list; +version (GNU) { + // va_list might be a pointer, but assuming so is not portable. + private import gcc.builtins; + alias __builtin_va_list va_list; + + // va_arg is handled magically by the compiler +} else { + alias void* va_list; +} template va_arg(T) { T va_arg(inout va_list _argptr) { + /* T arg = *cast(T*)_argptr; _argptr = _argptr + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1)); return arg; + */ + T t; return t; } } +private import std.c.stdarg; +/* The existence of std.stdarg.va_copy isn't standard. Prevent + conflicts by using '__'. */ +alias std.c.stdarg.va_copy __va_copy; diff -uNrp dmd-1.004/src/phobos/std/stdio.d gdc-0.22/d/phobos/std/stdio.d --- dmd-1.004/src/phobos/std/stdio.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/stdio.d 2006-12-17 06:03:04.000000000 +0100 @@ -6,6 +6,12 @@ * Placed in the Public Domain. */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, July 2006 +*/ + /******************************** * Standard I/O functions that extend $(B std.c.stdio). * $(B std.c.stdio) is automatically imported when importing @@ -20,6 +26,7 @@ public import std.c.stdio; import std.format; import std.utf; +import std.stdarg; version (DigitalMars) { @@ -51,10 +58,11 @@ else void __fp_unlock(FILE* fp) { } } -void writefx(FILE* fp, TypeInfo[] arguments, void* argptr, int newline=false) +void writefx(FILE* fp, TypeInfo[] arguments, va_list argptr, int newline=false) { int orientation; - orientation = fwide(fp, 0); + version(GNU_Have_fwide) + orientation = fwide(fp, 0); try { /* Do the file stream locking at the outermost level @@ -86,6 +94,9 @@ void writefx(FILE* fp, TypeInfo[] argume } else if (orientation > 0) // wide orientation { + version (GNU_Have_fwide) + { + version (Windows) { void putcw(dchar c) @@ -105,7 +116,7 @@ void writefx(FILE* fp, TypeInfo[] argume } } } - else version (linux) + else version (Unix) { void putcw(dchar c) { @@ -120,6 +131,8 @@ void writefx(FILE* fp, TypeInfo[] argume std.format.doFormat(&putcw, arguments, argptr); if (newline) FPUTWC('\n', fp); + + } } } finally diff -uNrp dmd-1.004/src/phobos/std/stream.d gdc-0.22/d/phobos/std/stream.d --- dmd-1.004/src/phobos/std/stream.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/stream.d 2006-12-17 06:03:04.000000000 +0100 @@ -20,6 +20,12 @@ * "as is" without express or implied warranty. */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, April 2005 +*/ + module std.stream; /* Class structure: @@ -183,7 +189,6 @@ interface InputStream { wchar[] readStringW(size_t length); - /*** * Read and return the next character in the stream. * @@ -192,6 +197,8 @@ interface InputStream { * If EOF is reached then getc returns char.init and getcw returns wchar.init. */ + // pushes back character c into the stream; only has + // effect on further calls to getc() and getcw() char getc(); wchar getcw(); /// ditto @@ -224,7 +231,7 @@ interface InputStream { * file.readf("%d hello %f", &x, &y, "%s", &s); * -------------------------- */ - int vreadf(TypeInfo[] arguments, void* args); + int vreadf(TypeInfo[] arguments, va_list args); int readf(...); /// ditto /// Retrieve the number of bytes available for immediate reading. @@ -343,14 +350,13 @@ interface OutputStream { */ OutputStream writef(...); OutputStream writefln(...); /// ditto - OutputStream writefx(TypeInfo[] arguments, void* argptr, int newline = false); /// ditto + OutputStream writefx(TypeInfo[] arguments, va_list argptr, int newline = false); /// ditto void flush(); /// Flush pending output if appropriate. void close(); /// Close the stream, flushing output if appropriate. bool isOpen(); /// Return true if the stream is currently open. } - /*** * Stream is the base abstract class from which the other stream classes derive. * @@ -679,7 +685,7 @@ class Stream : InputStream, OutputStream return c; } - int vreadf(TypeInfo[] arguments, void* args) { + int vreadf(TypeInfo[] arguments, va_list args) { char[] fmt; int j = 0; int count = 0, i = 0; @@ -1125,15 +1131,17 @@ class Stream : InputStream, OutputStream char* f = toStringz(format); size_t psize = buffer.length; size_t count; + va_list args_copy; while (true) { + __va_copy(args_copy, args); version (Win32) { - count = _vsnprintf(p, psize, f, args); + count = _vsnprintf(p, psize, f, args_copy); if (count != -1) break; psize *= 2; p = cast(char*) alloca(psize); - } else version (linux) { - count = vsnprintf(p, psize, f, args); + } else version (Unix) { + count = vsnprintf(p, psize, f, args_copy); if (count == -1) psize *= 2; else if (count >= psize) @@ -1151,10 +1159,14 @@ class Stream : InputStream, OutputStream // writes data to stream using printf() syntax, // returns number of bytes written size_t printf(char[] format, ...) { - va_list ap; - ap = cast(va_list) &format; - ap += format.sizeof; - return vprintf(format, ap); + version (GNU) + return vprintf(format, _argptr); + else { + va_list ap; + ap = cast(va_list) &format; + ap += format.sizeof; + return vprintf(format, ap); + } } private void doFormatCallback(dchar c) { @@ -1175,7 +1187,7 @@ class Stream : InputStream, OutputStream } // writes data with optional trailing newline - OutputStream writefx(TypeInfo[] arguments, void* argptr, int newline=false) { + OutputStream writefx(TypeInfo[] arguments, va_list argptr, int newline=false) { doFormat(&doFormatCallback,arguments,argptr); if (newline) writeLine(""); @@ -1774,8 +1786,8 @@ version (Win32) { DWORD GetFileType(HANDLE hFile); } } -version (linux) { - private import std.c.linux.linux; +version (Unix) { + private import std.c.unix.unix; alias int HANDLE; } @@ -1785,7 +1797,7 @@ class File: Stream { version (Win32) { private HANDLE hFile; } - version (linux) { + version (Unix) { private HANDLE hFile = -1; } @@ -1794,7 +1806,7 @@ class File: Stream { version (Win32) { hFile = null; } - version (linux) { + version (Unix) { hFile = -1; } isopen = false; @@ -1851,8 +1863,8 @@ class File: Stream { } isopen = hFile != INVALID_HANDLE_VALUE; } - version (linux) { - hFile = std.c.linux.linux.open(toStringz(filename), access | createMode, share); + version (Unix) { + hFile = std.c.unix.unix.open(toStringz(filename), access | createMode, share); isopen = hFile != -1; } if (!isopen) @@ -1879,7 +1891,7 @@ class File: Stream { createMode = CREATE_ALWAYS; // resets file } } - version (linux) { + version (Unix) { if (mode & FileMode.In) { access = O_RDONLY; share = 0660; @@ -1917,8 +1929,8 @@ class File: Stream { version (Win32) { CloseHandle(hFile); hFile = null; - } else version (linux) { - std.c.linux.linux.close(hFile); + } else version (Unix) { + std.c.unix.unix.close(hFile); hFile = -1; } } @@ -1942,8 +1954,8 @@ class File: Stream { assertReadable(); version (Win32) { ReadFile(hFile, buffer, size, &size, null); - } else version (linux) { - size = std.c.linux.linux.read(hFile, buffer, size); + } else version (Unix) { + size = std.c.unix.unix.read(hFile, buffer, size); if (size == -1) size = 0; } @@ -1955,8 +1967,8 @@ class File: Stream { assertWriteable(); version (Win32) { WriteFile(hFile, buffer, size, &size, null); - } else version (linux) { - size = std.c.linux.linux.write(hFile, buffer, size); + } else version (Unix) { + size = std.c.unix.unix.write(hFile, buffer, size); if (size == -1) size = 0; } @@ -1971,8 +1983,8 @@ class File: Stream { if ((low == INVALID_SET_FILE_POINTER) && (GetLastError() != 0)) throw new SeekException("unable to move file pointer"); ulong result = (cast(ulong)hi << 32) + low; - } else version (linux) { - ulong result = lseek(hFile, cast(int)offset, rel); + } else version (Unix) { + ulong result = lseek(hFile, cast(off_t)offset, rel); if (result == 0xFFFFFFFF) throw new SeekException("unable to move file pointer"); } @@ -2011,7 +2023,7 @@ class File: Stream { // string#1 + string#2 + int should give exacly that version (Win32) assert(file.position() == 19 + 13 + 4); - version (linux) + version (Unix) assert(file.position() == 18 + 13 + 4); // we must be at the end of file assert(file.eof()); @@ -2031,7 +2043,7 @@ class File: Stream { file.seek(7, SeekPos.Current); version (Win32) assert(file.position() == 19 + 7); - version (linux) + version (Unix) assert(file.position() == 18 + 7); assert(!std.string.cmp(file.readString(6), "world!")); i = 0; file.read(i); @@ -2039,7 +2051,7 @@ class File: Stream { // string#1 + string#2 + int should give exacly that version (Win32) assert(file.position() == 19 + 13 + 4); - version (linux) + version (Unix) assert(file.position() == 18 + 13 + 4); // we must be at the end of file assert(file.eof()); @@ -2128,7 +2140,7 @@ class BufferedFile: BufferedStream { // string#1 + string#2 + int should give exacly that version (Win32) assert(file.position() == 19 + 13 + 4); - version (linux) + version (Unix) assert(file.position() == 18 + 13 + 4); // we must be at the end of file assert(file.eof()); @@ -2148,7 +2160,7 @@ class BufferedFile: BufferedStream { file.seek(7, SeekPos.Current); version (Win32) assert(file.position() == 19 + 7); - version (linux) + version (Unix) assert(file.position() == 18 + 7); assert(!std.string.cmp(file.readString(6), "world!")); i = 0; file.read(i); @@ -2156,7 +2168,7 @@ class BufferedFile: BufferedStream { // string#1 + string#2 + int should give exacly that version (Win32) assert(file.position() == 19 + 13 + 4); - version (linux) + version (Unix) assert(file.position() == 18 + 13 + 4); // we must be at the end of file assert(file.eof()); diff -uNrp dmd-1.004/src/phobos/std/string.d gdc-0.22/d/phobos/std/string.d --- dmd-1.004/src/phobos/std/string.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/string.d 2006-12-17 06:03:04.000000000 +0100 @@ -25,6 +25,12 @@ // The code is not optimized for speed, that will have to wait // until the design is solidified. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + module std.string; //debug=string; // uncomment to turn on debugging printf's @@ -42,11 +48,11 @@ private import std.stdarg; extern (C) { - int wcslen(wchar *); int wcscmp(wchar *, wchar *); } + /* ************* Exceptions *************** */ /// Thrown on errors in string functions. @@ -75,7 +81,7 @@ const dchar PS = '\u2029'; /// UTF parag /// Newline sequence for this system version (Windows) const char[2] newline = "\r\n"; -else version (linux) +else version (Unix) const char[1] newline = "\n"; /********************************** @@ -148,7 +154,7 @@ int icmp(char[] s1, char[] s2) { result = memicmp(s1.ptr, s2.ptr, len); } - version (linux) + version (Unix) { for (size_t i = 0; i < len; i++) { @@ -1406,7 +1412,6 @@ unittest /************************************** * Split s[] into an array of lines, * using CR, LF, or CR-LF as the delimiter. - * The delimiter is not included in the line. */ char[][] splitlines(char[] s) @@ -2484,11 +2489,16 @@ char[] toString(double d) } /// ditto +static if (real.sizeof != double.sizeof) + private static const char[] _longDoubleFormat = "L"; +else + private static const char[] _longDoubleFormat = ""; + char[] toString(real r) { char[20] buffer; - int len = sprintf(buffer.ptr, "%Lg", r); + int len = sprintf(buffer.ptr, ("%"~_longDoubleFormat~"g").ptr, r); return buffer[0 .. len].dup; } @@ -2509,7 +2519,7 @@ char[] toString(ireal r) { char[21] buffer; - int len = sprintf(buffer.ptr, "%Lgi", r); + int len = sprintf(buffer.ptr, ("%"~_longDoubleFormat~"gi").ptr, r); return buffer[0 .. len].dup; } @@ -2530,11 +2540,10 @@ char[] toString(creal r) { char[20 + 1 + 20 + 1] buffer; - int len = sprintf(buffer.ptr, "%Lg+%Lgi", r.re, r.im); + int len = sprintf(buffer.ptr, ("%"~_longDoubleFormat~"g+%"~_longDoubleFormat~"gi").ptr, r.re, r.im); return buffer[0 .. len].dup; } - /****************************************** * Convert value to string in _radix radix. * diff -uNrp dmd-1.004/src/phobos/std/system.d gdc-0.22/d/phobos/std/system.d --- dmd-1.004/src/phobos/std/system.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/system.d 2006-12-17 06:03:04.000000000 +0100 @@ -7,6 +7,13 @@ * WIKI = Phobos/StdSystem */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + +// Information about the target operating system, environment, and CPU module std.system; @@ -18,6 +25,7 @@ const { Win32 = 1, // Microsoft 32 bit Windows systems linux, // all linux systems + Unix, // all other } version (Win32) @@ -28,6 +36,10 @@ const { Family family = Family.linux; } + else version (Unix) + { + Family family = Family.Unix; + } else { static assert(0); diff -uNrp dmd-1.004/src/phobos/std/thread.d gdc-0.22/d/phobos/std/thread.d --- dmd-1.004/src/phobos/std/thread.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/thread.d 2006-12-17 06:03:04.000000000 +0100 @@ -20,6 +20,12 @@ * distribution. */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, July 2006 +*/ + /************************** * The thread module defines the class $(B Thread). * @@ -179,9 +185,8 @@ class Thread } } - /****************************** - * Wait for this thread to terminate or until milliseconds time has - * elapsed, whichever occurs first. + /***************************** + * Wait for this thread to terminate. * Simply returns if thread has already terminated. * Throws: $(B ThreadError) if the thread hasn't begun yet or * is called on itself. @@ -447,6 +452,7 @@ class Thread { if (allThreadsDim) { + version (GNU) { /* unresolved issue: this CloseHandle call causes crashes later... */ } else CloseHandle(allThreads[0].hdl); allThreads[0].hdl = GetCurrentThread(); } @@ -496,83 +502,37 @@ void *os_query_stackBottom() } -/* ================================ linux ================================= */ +/* ================================ GCC ================================= */ -version (linux) +else version (GNU) { -private import std.c.linux.linux; -private import std.c.linux.linuxextern; +private import std.c.unix.unix; +private import gcc.builtins; -alias uint pthread_t; -extern (C) alias void (*__sighandler_t)(int); - -struct sigset_t +version (skyos) { - uint __val[1024 / (8 * uint.sizeof)]; + private import std.c.skyos.skyos; + private import std.c.skyos.compat; + alias std.c.skyos.compat.pthread_create pthread_create; + alias std.c.skyos.compat.pthread_join pthread_join; + alias std.c.skyos.compat.pthread_self pthread_self; + alias std.c.skyos.compat.pthread_kill pthread_kill; + alias std.c.skyos.compat.pthread_equal pthread_equal; + alias std.c.skyos.compat.sched_yield sched_yield; } -struct sigaction_t +version (GNU_pthread_suspend) { - __sighandler_t sa_handler; - sigset_t sa_mask; - int sa_flags; - void (*sa_restorer)(); + // nothing } - -struct pthread_attr_t +else { - int __detachstate; - int __schedpolicy; - struct __schedparam - { - int __sched_priority; - } - int __inheritsched; - int __scope; - size_t __guardsize; - int __stackaddr_set; - void *__stackaddr; - size_t __stacksize; + private import gcc.threadsem; } -unittest -{ - assert(sigset_t.sizeof == 128); - assert(sigaction_t.sizeof == 140); - assert(sem_t.sizeof == 16); -} +private extern (C) void* _d_gcc_query_stack_origin(); -extern (C) -{ - int pthread_create(pthread_t*, void*, void* (*)(void*), void*); - int pthread_join(pthread_t, void**); - int pthread_kill(pthread_t, int); - pthread_t pthread_self(); - int pthread_equal(pthread_t, pthread_t); - int pthread_attr_init(pthread_attr_t*); - int pthread_attr_setstacksize(pthread_attr_t *, size_t); - int pthread_cancel(pthread_t); - int pthread_setcancelstate(int, int*); - int pthread_setcanceltype(int, int*); - int sched_yield(); - int sigfillset(sigset_t*); - int sigdelset(sigset_t*, int); - int sigaction(int, sigaction_t*, sigaction_t*); - int sigsuspend(sigset_t*); - - enum - { - PTHREAD_CANCEL_ENABLE, - PTHREAD_CANCEL_DISABLE - } - - enum - { - PTHREAD_CANCEL_DEFERRED, - PTHREAD_CANCEL_ASYNCHRONOUS - } -} class ThreadError : Error { @@ -634,20 +594,20 @@ class Thread } } nthreads++; - } - state = TS.RUNNING; - int result; - //printf("creating thread x%x\n", this); - //result = pthread_create(&id, null, &threadstart, this); - // Create with thread attributes to allow non-default stack size - Dave Fladebo - result = pthread_create(&id, &threadAttrs, &threadstart, this); - if (result) - { state = TS.TERMINATED; - allThreads[idx] = null; - idx = -1; - error("failed to start"); // BUG: should report errno - } + state = TS.RUNNING; + int result; + //printf("creating thread x%x\n", this); + //result = pthread_create(&id, null, &threadstart, this); + // Create with thread attributes to allow non-default stack size - Dave Fladebo + result = pthread_create(&id, &threadAttrs, &threadstart, this); + if (result) + { state = TS.TERMINATED; + allThreads[idx] = null; + idx = -1; + error("failed to start"); // BUG: should report errno + } + } // %% changed end of sync region //printf("t = x%x, id = %d\n", this, id); } @@ -696,6 +656,8 @@ class Thread timespec ts; timeval tv; + alias typeof(tv.tv_sec) __time_t; + pthread_mutex_lock(&waitMtx); gettimeofday(&tv, null); ts.tv_sec = cast(__time_t)tv.tv_sec + cast(__time_t)(milliseconds / 1_000); @@ -793,7 +755,7 @@ class Thread Thread result; //printf("getThis(), allThreadsDim = %d\n", allThreadsDim); - synchronized (threadLock) + //synchronized (threadLock) { id = pthread_self(); //printf("id = %d\n", id); @@ -820,13 +782,21 @@ class Thread void pause() { if (state == TS.RUNNING) - { int result; - - result = pthread_kill(id, SIGUSR1); - if (result) - error("cannot pause"); + { + version (GNU_pthread_suspend) + { + if (pthread_suspend_np(id) != 0) + error("cannot pause"); + } else - sem_wait(&flagSuspend); // wait for acknowledgement + { int result; + + result = pthread_kill(id, SIGUSR1); + if (result) + error("cannot pause"); + else + flagSuspend.wait(); // wait for acknowledgement + } } else error("cannot pause"); @@ -835,11 +805,19 @@ class Thread void resume() { if (state == TS.RUNNING) - { int result; + { + version (GNU_pthread_suspend) + { + if (pthread_continue_np(id) != 0) + error("cannot pause"); + } + else + { int result; - result = pthread_kill(id, SIGUSR2); - if (result) - error("cannot resume"); + result = pthread_kill(id, SIGUSR2); + if (result) + error("cannot resume"); + } } else error("cannot resume"); @@ -847,11 +825,37 @@ class Thread static void pauseAll() { + version (GNU_pthread_suspend) + { + if (nthreads > 1) + { + Thread tthis = getThis(); + + synchronized (threadLock) + { + + for (int i = 0; i < allThreadsDim; i++) + { Thread t; + + t = allThreads[i]; + if (t && t !is tthis && t.state == TS.RUNNING) + t.pause(); + } + + } + } + } + else + { + if (nthreads > 1) { Thread tthis = getThis(); int npause = 0; + synchronized (threadLock) + { + for (int i = 0; i < allThreadsDim; i++) { Thread t; @@ -867,12 +871,16 @@ class Thread } } + } + // Wait for each paused thread to acknowledge while (npause--) { - sem_wait(&flagSuspend); + flagSuspend.wait(); } } + + } } static void resumeAll() @@ -902,13 +910,20 @@ class Thread static uint allThreadsDim; static Object threadLock; - + // Set max to Windows equivalent for compatibility. // pthread_create will fail gracefully if stack limit // is reached prior to allThreads max. static Thread[0x400] allThreads; - - static sem_t flagSuspend; + + version (GNU_pthread_suspend) + { + // nothing + } + else + { + static Semaphore flagSuspend; + } TS state; int idx = -1; // index into allThreads[] @@ -962,6 +977,9 @@ class Thread // before pthread_create() sets it. t.id = pthread_self(); + version(skyos) + installSignalHandlers(); + t.stackBottom = getESP(); try { @@ -977,10 +995,13 @@ class Thread } debug (thread) printf("Ending thread %d\n", t.idx); - t.state = TS.TERMINATED; - allThreads[t.idx] = null; - t.idx = -1; - nthreads--; + synchronized (threadLock) + { + t.state = TS.TERMINATED; + allThreads[t.idx] = null; + t.idx = -1; + nthreads--; + } return cast(void*)result; } @@ -997,118 +1018,117 @@ class Thread t.state = TS.RUNNING; t.id = pthread_self(); - - version (none) - { - // See discussion: http://autopackage.org/forums/viewtopic.php?t=22 - static void** libc_stack_end; - - if (libc_stack_end == libc_stack_end.init) - { - void* handle = dlopen(null, RTLD_NOW); - libc_stack_end = cast(void **)dlsym(handle, "__libc_stack_end"); - dlclose(handle); - } - t.stackBottom = *libc_stack_end; - } - else - { - t.stackBottom = cast(void*)__libc_stack_end; - } + t.stackBottom = cast(void*) _d_gcc_query_stack_origin(); assert(!allThreads[0]); allThreads[0] = t; allThreadsDim = 1; t.idx = 0; - /* Install signal handlers so we can suspend/resume threads - */ - - int result; - sigaction_t sigact; - result = sigfillset(&sigact.sa_mask); - if (result) - goto Lfail; - sigact.sa_handler = &pauseHandler; - result = sigaction(SIGUSR1, &sigact, null); - if (result) - goto Lfail; - sigact.sa_handler = &resumeHandler; - result = sigaction(SIGUSR2, &sigact, null); - if (result) - goto Lfail; - - result = sem_init(&flagSuspend, 0, 0); - if (result) - goto Lfail; + version (GNU_pthread_suspend) + { + // nothing + } + else + { + /* Install signal handlers so we can suspend/resume threads + */ + installSignalHandlers(); + } return; - Lfail: - getThis().error("cannot initialize threads"); } - /********************************** - * This gets called when a thread gets SIGUSR1. - */ + version (GNU_pthread_suspend) + { + // nothing + } + else + { + + private static void installSignalHandlers() + { + int result; + sigaction_t sigact; + result = sigfillset(&sigact.sa_mask); + if (result) + goto Lfail; + sigact.sa_handler = &pauseHandler; + result = sigaction(SIGUSR1, &sigact, null); + if (result) + goto Lfail; + sigact.sa_handler = &resumeHandler; + result = sigaction(SIGUSR2, &sigact, null); + if (result) + goto Lfail; - extern (C) static void pauseHandler(int sig) - { int result; + if (! flagSuspend.create()) + goto Lfail; - // Save all registers on the stack so they'll be scanned by the GC - asm - { - pusha ; + return; + Lfail: + getThis().error("cannot initialize threads"); } - assert(sig == SIGUSR1); + + /********************************** + * This gets called when a thread gets SIGUSR1. + */ - sigset_t sigmask; - result = sigfillset(&sigmask); - assert(result == 0); - result = sigdelset(&sigmask, SIGUSR2); - assert(result == 0); + extern (C) static void pauseHandler(int sig) + { int result; - Thread t = getThis(); - t.stackTop = getESP(); - t.flags &= ~1; - // Release the semaphore _after_ stackTop is set - sem_post(&flagSuspend); - while (1) - { - sigsuspend(&sigmask); // suspend until SIGUSR2 - if (t.flags & 1) // ensure it was resumeHandler() - break; - } + // Save all registers on the stack so they'll be scanned by the GC + __builtin_unwind_init(); - // Restore all registers - asm - { - popa ; + + assert(sig == SIGUSR1); + + sigset_t sigmask; + result = sigfillset(&sigmask); + assert(result == 0); + result = sigdelset(&sigmask, SIGUSR2); + assert(result == 0); + + Thread t = getThis(); + t.stackTop = getESP(); + t.flags &= ~1; + flagSuspend.signal(); + while (1) + { + sigsuspend(&sigmask); // suspend until SIGUSR2 + if (t.flags & 1) // ensure it was resumeHandler() + break; + } } - } - /********************************** - * This gets called when a thread gets SIGUSR2. - */ + /********************************** + * This gets called when a thread gets SIGUSR2. + */ - extern (C) static void resumeHandler(int sig) - { - Thread t = getThis(); + extern (C) static void resumeHandler(int sig) + { + Thread t = getThis(); - t.flags |= 1; + t.flags |= 1; + } } public static void* getESP() { - asm - { naked ; - mov EAX,ESP ; - ret ; - } + // TODO add builtin for using stack_pointer_rtx + int dummy; + void * p = & dummy + 1; // +1 doesn't help much; also assume stack grows down + return p; } } } + +else +{ + static assert(0); +} diff -uNrp dmd-1.004/src/phobos/std/typeinfo/ti_Abit.d gdc-0.22/d/phobos/std/typeinfo/ti_Abit.d --- dmd-1.004/src/phobos/std/typeinfo/ti_Abit.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/std/typeinfo/ti_Abit.d 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,97 @@ + +module std.typeinfo.ti_Abit; + +private import std.string; + +// bit[] + +class TypeInfo_Ab : TypeInfo +{ + char[] toString() { return "bit[]"; } + + uint getHash(void *p) + { ubyte[] s = *cast(ubyte[]*)p; + size_t len = (s.length + 7) / 8; + ubyte *str = s; + uint hash = 0; + + while (1) + { + switch (len) + { + case 0: + return hash; + + case 1: + hash *= 9; + hash += *cast(ubyte *)str; + return hash; + + case 2: + hash *= 9; + hash += *cast(ushort *)str; + return hash; + + case 3: + hash *= 9; + hash += (*cast(ushort *)str << 8) + + (cast(ubyte *)str)[2]; + return hash; + + default: + hash *= 9; + hash += *cast(uint *)str; + str += 4; + len -= 4; + break; + } + } + + return hash; + } + + int equals(void *p1, void *p2) + { + bit[] s1 = *cast(bit[]*)p1; + bit[] s2 = *cast(bit[]*)p2; + + size_t len = s1.length; + + if (s2.length != len) + return 0;; + + // Woefully inefficient bit-by-bit comparison + for (size_t u = 0; u < len; u++) + { + if (s1[u] != s2[u]) + return 0; + } + return 1; + } + + int compare(void *p1, void *p2) + { + bit[] s1 = *cast(bit[]*)p1; + bit[] s2 = *cast(bit[]*)p2; + + size_t len = s1.length; + + if (s2.length < len) + len = s2.length; + + // Woefully inefficient bit-by-bit comparison + for (size_t u = 0; u < len; u++) + { + int result = s1[u] - s2[u]; + if (result) + return result; + } + return cast(int)s1.length - cast(int)s2.length; + } + + size_t tsize() + { + return (bit[]).sizeof; + } +} + diff -uNrp dmd-1.004/src/phobos/std/typeinfo/ti_bit.d gdc-0.22/d/phobos/std/typeinfo/ti_bit.d --- dmd-1.004/src/phobos/std/typeinfo/ti_bit.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/std/typeinfo/ti_bit.d 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,43 @@ + +// bit + +module std.typeinfo.ti_bit; + +class TypeInfo_b : TypeInfo +{ + char[] toString() { return "bit"; } + + uint getHash(void *p) + { + return *cast(bit *)p; + } + + int equals(void *p1, void *p2) + { + return *cast(bit *)p1 == *cast(bit *)p2; + } + + int compare(void *p1, void *p2) + { + if (*cast(bit*) p1 < *cast(bit*) p2) + return -1; + else if (*cast(bit*) p1 > *cast(bit*) p2) + return 1; + return 0; + } + + size_t tsize() + { + return bit.sizeof; + } + + void swap(void *p1, void *p2) + { + bit t; + + t = *cast(bit *)p1; + *cast(bit *)p1 = *cast(bit *)p2; + *cast(bit *)p2 = t; + } +} + diff -uNrp dmd-1.004/src/phobos/std/uri.d gdc-0.22/d/phobos/std/uri.d --- dmd-1.004/src/phobos/std/uri.d 2007-01-26 22:58:40.000000000 +0100 +++ gdc-0.22/d/phobos/std/uri.d 2006-12-17 06:03:04.000000000 +0100 @@ -420,7 +420,8 @@ unittest //printf("r = '%.*s'\n", r); assert(r == "c%2B%2B"); - char[] str = new char[10_000_000]; + // char[] str = new char[10_000_000]; // Belongs in testgc.d? 8-\ + char[] str = new char[10_000]; str[] = 'A'; r = encodeComponent(str); foreach (char c; r) diff -uNrp dmd-1.004/src/phobos/std/windows/registry.d gdc-0.22/d/phobos/std/windows/registry.d --- dmd-1.004/src/phobos/std/windows/registry.d 2007-01-26 22:58:42.000000000 +0100 +++ gdc-0.22/d/phobos/std/windows/registry.d 2006-12-17 06:03:04.000000000 +0100 @@ -8,7 +8,7 @@ * * Author: Matthew Wilson * - * License: (Licensed under the Synesis Software Standard Source License) + * License: * * Copyright (C) 2002-2004, Synesis Software Pty Ltd. * @@ -20,25 +20,19 @@ * email: submissions@synsoft.org for submissions * admin@synsoft.org for other enquiries * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * (i) Redistributions of source code must retain the above - * copyright notice and contact information, this list of - * conditions and the following disclaimer. - * - * (ii) Any derived versions of this software (howsoever modified) - * remain the sole property of Synesis Software. - * - * (iii) Any derived versions of this software (howsoever modified) - * remain subject to all these conditions. - * - * (iv) Neither the name of Synesis Software nor the names of any - * subdivisions, employees or agents of Synesis Software, nor the - * names of any other contributors to this software may be used to - * endorse or promote products derived from this software without - * specific prior written permission. + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, in both source and binary form, subject to the following + * restrictions: + * + * - The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * - Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * - This notice may not be removed or altered from any source + * distribution. * * This source code is provided by Synesis Software "as is" and any * warranties, whether expressed or implied, including, but not