diff -uNrp dmd-0.162/src/dmd/constfold.c gdc-0.19/d/dmd/constfold.c --- dmd-0.162/src/dmd/constfold.c 2006-04-12 10:49:22.000000000 +0200 +++ gdc-0.19/d/dmd/constfold.c 2006-06-02 05:31:29.000000000 +0200 @@ -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 @@ -133,7 +139,11 @@ Expression *CastExp::constFold() { if (e1->type->isfloating()) { integer_t result; +#ifdef IN_GCC + d_int64 r = e1->toReal().toInt(e1->type, type); +#else real_t r = e1->toReal(); +#endif switch (type->toBasetype()->ty) { @@ -419,7 +429,7 @@ Expression *MulExp::constFold() #ifdef IN_GCC real_t r; #else - d_float80 r; + d_float80 r; #endif if (e1->type->isreal()) @@ -492,7 +502,7 @@ Expression *DivExp::constFold() #ifdef IN_GCC real_t r; #else - d_float80 r; + d_float80 r; #endif //e1->type->print(); @@ -950,7 +960,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-0.162/src/dmd/dchar.c gdc-0.19/d/dmd/dchar.c --- dmd-0.162/src/dmd/dchar.c 2006-02-12 22:59:04.000000000 +0100 +++ gdc-0.19/d/dmd/dchar.c 2006-06-02 05:31:29.000000000 +0200 @@ -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, February 2005 +*/ + #include #include @@ -326,18 +332,30 @@ unsigned Dchar::calcHash(const dchar *st case 2: hash *= 37; +#if __I86__ hash += *(unsigned short *)str; +#else + hash += str[0] * 256 + str[1]; +#endif return hash; case 3: hash *= 37; +#if __I86__ hash += (*(unsigned short *)str << 8) + ((unsigned char *)str)[2]; +#else + hash += (str[0] * 256 + str[1]) * 256 + str[2]; +#endif return hash; default: hash *= 37; +#if __I86__ hash += *(long *)str; +#else + hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3]; +#endif str += 4; len -= 4; break; @@ -365,30 +383,21 @@ unsigned Dchar::calcHash(const dchar *st case 2: hash *= 37; -#if __I86__ - hash += *(unsigned short *)str; -#else hash += str[0] * 256 + str[1]; -#endif +/* hash += *(unsigned short *)str; */ return hash; case 3: hash *= 37; -#if __I86__ - hash += (*(unsigned short *)str << 8) + - ((unsigned char *)str)[2]; -#else hash += (str[0] * 256 + str[1]) * 256 + str[2]; -#endif +/* hash += (*(unsigned short *)str << 8) + + ((unsigned char *)str)[2]; */ return hash; default: hash *= 37; -#if __I86__ - hash += *(long *)str; -#else hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3]; -#endif +/* hash += *(long*)str; */ str += 4; len -= 4; break; diff -uNrp dmd-0.162/src/dmd/declaration.h gdc-0.19/d/dmd/declaration.h --- dmd-0.162/src/dmd/declaration.h 2006-06-09 23:36:12.000000000 +0200 +++ gdc-0.19/d/dmd/declaration.h 2006-06-21 05:12:11.000000000 +0200 @@ -415,7 +415,8 @@ struct FuncDeclaration : Declaration Expression *doInline(InlineScanState *iss, Expression *ethis, Array *arguments); char *kind(); - 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-0.162/src/dmd/expression.c gdc-0.19/d/dmd/expression.c --- dmd-0.162/src/dmd/expression.c 2006-06-28 01:01:30.000000000 +0200 +++ gdc-0.19/d/dmd/expression.c 2006-07-03 16:46:40.000000000 +0200 @@ -7,12 +7,25 @@ // 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 #include #include +#ifdef __APPLE__ +#define integer_t dmd_integer_t +#endif + #if __GNUC__ extern "C" long double strtold(const char *p,char **endp); #endif @@ -22,22 +35,12 @@ extern "C" char * __cdecl __locale_decpo #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 IN_GCC #include "mem.h" #elif _WIN32 #include "..\root\mem.h" #elif linux #include "../root/mem.h" #endif - #include "port.h" #include "mtype.h" #include "init.h" @@ -720,7 +723,7 @@ void Expression::toCBuffer(OutBuffer *bu void Expression::toMangleBuffer(OutBuffer *buf) { - printf("global.errors = %d, gag = %d\n", global.errors, global.gag); + fprintf(stdmsg, "global.errors = %d, gag = %d\n", global.errors, global.gag); dump(0); assert(0); } @@ -1226,7 +1229,12 @@ int RealExp::equals(Object *o) if (this == o || (((Expression *)o)->op == TOKfloat64 && ((ne = (RealExp *)o), type->equals(ne->type)) && - memcmp(&value, &ne->value, sizeof(value)) == 0)) +#ifdef IN_GCC + value.isIdenticalTo(ne->value) +#else + memcmp(&value, &ne->value, sizeof(value)) == 0 +#endif + )) return 1; return 0; } @@ -1250,14 +1258,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__ @@ -1272,6 +1293,7 @@ void floatToBuffer(OutBuffer *buf, Type buf->writestring(buffer); else buf->printf("%La", value); // ensure exact duplication +#endif if (type) { @@ -1383,7 +1405,13 @@ int ComplexExp::equals(Object *o) if (this == o || (((Expression *)o)->op == TOKcomplex80 && ((ne = (ComplexExp *)o), type->equals(ne->type)) && - memcmp(&value, &ne->value, sizeof(value)) == 0)) +#ifdef IN_GCC + (value.re.isIdenticalTo(ne->value.re) && + value.im.isIdenticalTo(ne->value.im)) +#else + memcmp(&value, &ne->value, sizeof(value)) == 0 +#endif + )) return 1; return 0; } diff -uNrp dmd-0.162/src/dmd/expression.h gdc-0.19/d/dmd/expression.h --- dmd-0.162/src/dmd/expression.h 2006-06-07 17:25:36.000000000 +0200 +++ gdc-0.19/d/dmd/expression.h 2006-06-21 05:12:11.000000000 +0200 @@ -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 +*/ + #ifndef DMD_EXPRESSION_H #define DMD_EXPRESSION_H diff -uNrp dmd-0.162/src/dmd/func.c gdc-0.19/d/dmd/func.c --- dmd-0.162/src/dmd/func.c 2006-06-28 15:06:52.000000000 +0200 +++ gdc-0.19/d/dmd/func.c 2006-07-03 16:46:40.000000000 +0200 @@ -1529,7 +1529,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; @@ -1554,7 +1555,19 @@ FuncDeclaration *FuncDeclaration::genCfu } else { - tf = new TypeFunction(NULL, treturn, 0, LINKc); + Array * args = 0; + if (t1) { + args = new Array; + 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-0.162/src/dmd/html.c gdc-0.19/d/dmd/html.c --- dmd-0.162/src/dmd/html.c 2005-05-25 21:51:30.000000000 +0200 +++ gdc-0.19/d/dmd/html.c 2006-06-02 05:31:29.000000000 +0200 @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2005 by Digital Mars +// Copyright (c) 1999-2002 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 + Modified by Thomas Kuehne, November 2004 +*/ /* HTML parser */ @@ -16,18 +22,18 @@ #include #include #include -#include +//#include #include "mars.h" #include "html.h" #include #include "root.h" -#include "../mars/mars.h" +//#include "../mars/mars.h" -#if __GNUC__ -int memicmp(const char *s1, const char *s2, int n); -#endif +//#if __GNUC__ +//int memicmp(const char *s1, const char *s2, int n); +//#endif extern int HtmlNamedEntity(unsigned char *p, int length); @@ -38,7 +44,7 @@ extern int HtmlNamedEntity(unsigned char inline int istagstart(int c) { - return (isalpha(c) || c == '_'); + return (isalpha(c) || c == '_' || c == '!'); } inline int istag(int c) @@ -46,12 +52,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; @@ -69,18 +104,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(); } /********************************************** @@ -104,16 +140,27 @@ 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; } @@ -443,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 '<' @@ -527,6 +626,7 @@ int Html::charEntity() } else hex = 0; + if (p[1] == ';') goto Linvalid; while (1) @@ -630,10 +730,8 @@ 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; diff -uNrp dmd-0.162/src/dmd/identifier.c gdc-0.19/d/dmd/identifier.c --- dmd-0.162/src/dmd/identifier.c 2006-02-15 00:07:28.000000000 +0100 +++ gdc-0.19/d/dmd/identifier.c 2006-06-02 05:31:29.000000000 +0200 @@ -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, May 2005 +*/ + #include #include diff -uNrp dmd-0.162/src/dmd/lexer.c gdc-0.19/d/dmd/lexer.c --- dmd-0.162/src/dmd/lexer.c 2006-06-10 00:01:32.000000000 +0200 +++ gdc-0.19/d/dmd/lexer.c 2006-06-21 05:12:11.000000000 +0200 @@ -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 +*/ + /* Lexical Analyzer */ #include @@ -14,7 +20,7 @@ #include #include #include -#include +//#include #include #include #include @@ -120,7 +126,7 @@ char *Token::toChars() #if IN_GCC sprintf(buffer,"%ld",(d_int32)int64value); #else - sprintf(buffer,"%ld",int32value); + sprintf(buffer,"%ld",int32value); #endif break; @@ -131,7 +137,7 @@ char *Token::toChars() #if IN_GCC sprintf(buffer,"%luU",(d_uns32)uns64value); #else - sprintf(buffer,"%luU",uns32value); + sprintf(buffer,"%luU",uns32value); #endif break; @@ -182,6 +188,7 @@ char *Token::toChars() break; #endif + case TOKstring: #if CSTRINGS p = string; @@ -329,7 +336,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-0.162/src/dmd/mars.h gdc-0.19/d/dmd/mars.h --- dmd-0.162/src/dmd/mars.h 2006-06-15 01:17:38.000000000 +0200 +++ gdc-0.19/d/dmd/mars.h 2006-06-21 05:12:11.000000000 +0200 @@ -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 +*/ + #ifndef DMD_MARS_H #define DMD_MARS_H @@ -71,7 +77,7 @@ struct Param Array *versionids; // version identifiers bool dump_source; - + // Hidden debug switches char debuga; char debugb; @@ -164,7 +170,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 diff -uNrp dmd-0.162/src/dmd/mem.c gdc-0.19/d/dmd/mem.c --- dmd-0.162/src/dmd/mem.c 2005-04-27 01:21:12.000000000 +0200 +++ gdc-0.19/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-0.162/src/dmd/mem.h gdc-0.19/d/dmd/mem.h --- dmd-0.162/src/dmd/mem.h 2004-03-27 00:11:52.000000000 +0100 +++ gdc-0.19/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 -typedef unsigned size_t; +#include // for size_t typedef void (*FINALIZERPROC)(void* pObj, void* pClientData); diff -uNrp dmd-0.162/src/dmd/mtype.c gdc-0.19/d/dmd/mtype.c --- dmd-0.162/src/dmd/mtype.c 2006-06-28 21:04:26.000000000 +0200 +++ gdc-0.19/d/dmd/mtype.c 2006-07-03 16:46:40.000000000 +0200 @@ -7,6 +7,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, September 2004 +*/ + +// 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 @@ -14,15 +23,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 @@ -33,11 +48,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" @@ -618,6 +648,7 @@ void Type::error(Loc loc, const char *fo fflush(stdmsg); } global.errors++; + //fatal(); } Identifier *Type::getTypeInfoIdent(int internal) @@ -921,6 +952,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: @@ -1187,7 +1250,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: @@ -1217,7 +1280,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: @@ -1397,7 +1460,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(n->arrayOf()); // convert to dynamic array arguments = new Expressions(); @@ -1417,7 +1480,8 @@ Expression *TypeArray::dotExp(Scope *sc, assert(size); nm = name[n->ty == Tbit][ident == Id::dup]; - fd = FuncDeclaration::genCfunc(Type::tindex, nm); + fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), nm, + Type::tvoid->arrayOf(), next->ty != Tbit ? Type::tint32 : NULL); ec = new VarExp(0, fd); e = e->castTo(n->arrayOf()); // convert to dynamic array arguments = new Expressions(); @@ -1434,7 +1498,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(n->arrayOf()); // convert to dynamic array arguments = new Expressions(); @@ -1944,7 +2010,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); @@ -1969,7 +2035,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); @@ -1984,7 +2051,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); @@ -2001,7 +2069,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()); diff -uNrp dmd-0.162/src/dmd/mtype.h gdc-0.19/d/dmd/mtype.h --- dmd-0.162/src/dmd/mtype.h 2006-03-18 14:17:58.000000000 +0100 +++ gdc-0.19/d/dmd/mtype.h 2006-06-02 05:31:29.000000000 +0200 @@ -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 +*/ + #ifndef DMD_MTYPE_H #define DMD_MTYPE_H diff -uNrp dmd-0.162/src/dmd/opover.c gdc-0.19/d/dmd/opover.c --- dmd-0.162/src/dmd/opover.c 2006-06-07 00:51:18.000000000 +0200 +++ gdc-0.19/d/dmd/opover.c 2006-06-21 05:12:11.000000000 +0200 @@ -6,6 +6,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-0.162/src/dmd/optimize.c gdc-0.19/d/dmd/optimize.c --- dmd-0.162/src/dmd/optimize.c 2006-04-26 12:09:06.000000000 +0200 +++ gdc-0.19/d/dmd/optimize.c 2006-06-02 05:31:29.000000000 +0200 @@ -428,6 +428,7 @@ Expression *CatExp::optimize(int result) { // Concatenate the strings void *s; + void *sch; StringExp *es1 = (StringExp *)e1; StringExp *es; Type *t; @@ -437,7 +438,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); @@ -463,7 +471,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-0.162/src/dmd/parse.c gdc-0.19/d/dmd/parse.c --- dmd-0.162/src/dmd/parse.c 2006-06-30 00:35:56.000000000 +0200 +++ gdc-0.19/d/dmd/parse.c 2006-07-03 16:46:40.000000000 +0200 @@ -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 @@ -3640,12 +3646,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; @@ -3705,17 +3711,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-0.162/src/dmd/port.h gdc-0.19/d/dmd/port.h --- dmd-0.162/src/dmd/port.h 2004-03-27 00:11:52.000000000 +0100 +++ gdc-0.19/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-0.162/src/dmd/root.c gdc-0.19/d/dmd/root.c --- dmd-0.162/src/dmd/root.c 2006-06-17 22:23:36.000000000 +0200 +++ gdc-0.19/d/dmd/root.c 2006-06-21 05:12:11.000000000 +0200 @@ -7,22 +7,26 @@ // 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 #include #include -#if _MSC_VER -#include -#endif +#include "gdc_alloca.h" #if _WIN32 #include #include #endif -#if linux +#ifndef _WIN32 #include #include #include @@ -45,6 +49,7 @@ extern "C" void __cdecl _assert(void *e, } #endif +#ifndef IN_GCC /************************************* * Convert wchar string to ascii string. */ @@ -81,6 +86,7 @@ int wcharIsAscii(wchar_t *us, unsigned l } return 1; } +#endif /*********************************** @@ -116,11 +122,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); } @@ -131,11 +137,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); } @@ -155,11 +161,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 ********************************/ @@ -181,7 +187,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() @@ -299,7 +305,7 @@ char *String::toChars() void String::print() { - printf("String '%s'\n",str); + fprintf(stderr, "String '%s'\n",str); } @@ -321,14 +327,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++; } @@ -375,7 +381,7 @@ Array *FileName::splitPath(const char *p #if _WIN32 case ';': #endif -#if linux +#ifndef _WIN32 case ':': #endif p++; @@ -389,7 +395,7 @@ Array *FileName::splitPath(const char *p case '\r': continue; // ignore carriage returns -#if linux +#ifndef _WIN32 case '~': buf.writestring(getenv("HOME")); continue; @@ -417,7 +423,8 @@ Array *FileName::splitPath(const char *p unsigned FileName::hashCode() { -#if linux +#ifndef _WIN32 + // darwin HFS is case insensitive, though... return String::hashCode(); #endif #if _WIN32 @@ -462,7 +469,7 @@ unsigned FileName::hashCode() int FileName::compare(Object *obj) { -#if linux +#ifndef _WIN32 return String::compare(obj); #endif #if _WIN32 @@ -472,7 +479,7 @@ int FileName::compare(Object *obj) int FileName::equals(Object *obj) { -#if linux +#ifndef _WIN32 return String::equals(obj); #endif #if _WIN32 @@ -491,7 +498,7 @@ int FileName::absolute(const char *name) (*name == '/') || (*name && name[1] == ':'); #endif -#if linux +#ifndef _WIN32 return (*name == '/'); #endif } @@ -512,11 +519,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; @@ -550,11 +558,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; @@ -587,12 +596,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 } @@ -623,14 +632,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++; } @@ -699,7 +708,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 @@ -718,7 +727,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(); @@ -760,7 +769,7 @@ char *FileName::searchPath(Array *path, int FileName::exists(const char *name) { -#if linux +#ifndef _WIN32 struct stat st; if (stat(name, &st) < 0) @@ -871,7 +880,7 @@ void File::mark() int File::read() { -#if linux +#ifndef _WIN32 off_t size; ssize_t numread; int fd; @@ -895,21 +904,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; } @@ -918,7 +927,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; } @@ -1003,7 +1012,7 @@ err1: int File::mmread() { -#if linux +#ifndef _WIN32 return read(); #endif #if _WIN32 @@ -1057,7 +1066,7 @@ Lerr: int File::write() { -#if linux +#ifndef _WIN32 int fd; ssize_t numwritten; char *name; @@ -1128,7 +1137,7 @@ err: int File::append() { -#if linux +#ifndef _WIN32 return 1; #endif #if _WIN32 @@ -1208,7 +1217,7 @@ void File::appendv() int File::exists() { -#if linux +#ifndef _WIN32 return 0; #endif #if _WIN32 @@ -1233,7 +1242,7 @@ int File::exists() void File::remove() { -#if linux +#ifndef _WIN32 ::remove(this->name->toChars()); #endif #if _WIN32 @@ -1248,7 +1257,7 @@ Array *File::match(char *n) Array *File::match(FileName *n) { -#if linux +#ifndef _WIN32 return NULL; #endif #if _WIN32 @@ -1286,7 +1295,7 @@ Array *File::match(FileName *n) int File::compareTime(File *f) { -#if linux +#ifndef _WIN32 return 0; #endif #if _WIN32 @@ -1300,7 +1309,7 @@ int File::compareTime(File *f) void File::stat() { -#if linux +#ifndef _WIN32 if (!touchtime) { touchtime = mem.calloc(1, sizeof(struct stat)); @@ -1594,19 +1603,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) @@ -1626,19 +1637,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-0.162/src/dmd/root.h gdc-0.19/d/dmd/root.h --- dmd-0.162/src/dmd/root.h 2006-06-17 10:41:06.000000000 +0200 +++ gdc-0.19/d/dmd/root.h 2006-06-21 05:12:11.000000000 +0200 @@ -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 @@ -27,9 +33,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 diff -uNrp dmd-0.162/src/dmd/scope.c gdc-0.19/d/dmd/scope.c --- dmd-0.162/src/dmd/scope.c 2006-02-22 01:22:04.000000000 +0100 +++ gdc-0.19/d/dmd/scope.c 2006-06-02 05:31:29.000000000 +0200 @@ -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, May 2005 +*/ + #include #include diff -uNrp dmd-0.162/src/dmd/statement.c gdc-0.19/d/dmd/statement.c --- dmd-0.162/src/dmd/statement.c 2006-06-16 09:47:54.000000000 +0200 +++ gdc-0.19/d/dmd/statement.c 2006-06-21 05:12:11.000000000 +0200 @@ -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 @@ -1124,15 +1130,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); args = new Expressions(); args->push(aggr); size_t keysize = taa->key->size(); keysize = (keysize + 3) & ~3; - args->push(new IntegerExp(0, keysize, Type::tint32)); + args->push(new IntegerExp(0, keysize, Type::tsize_t)); args->push(flde); e = new CallExp(loc, ec, args); e->type = Type::tindex; // don't run semantic() on e @@ -1166,7 +1174,8 @@ Statement *ForeachStatement::semantic(Sc } int j = sprintf(fdname, "_aApply%.*s%d", 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); args = new Expressions(); @@ -1846,7 +1855,7 @@ DefaultStatement::DefaultStatement(Loc l { this->statement = s; #if IN_GCC -+ cblock = NULL; + cblock = NULL; #endif } diff -uNrp dmd-0.162/src/dmd/struct.c gdc-0.19/d/dmd/struct.c --- dmd-0.162/src/dmd/struct.c 2006-06-28 15:59:14.000000000 +0200 +++ gdc-0.19/d/dmd/struct.c 2006-07-03 16:46:40.000000000 +0200 @@ -244,6 +244,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(); diff -uNrp dmd-0.162/src/dmd/template.c gdc-0.19/d/dmd/template.c --- dmd-0.162/src/dmd/template.c 2006-06-30 00:16:30.000000000 +0200 +++ gdc-0.19/d/dmd/template.c 2006-07-12 09:29:27.000000000 +0200 @@ -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 +*/ + // Handle template implementation #include @@ -1218,7 +1224,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); @@ -1226,11 +1232,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()); } @@ -1403,12 +1409,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) @@ -1619,13 +1625,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"); } @@ -1697,6 +1703,9 @@ TemplateInstance::TemplateInstance(Loc l this->semanticdone = 0; this->withsym = NULL; this->nest = 0; +#ifdef IN_GCC + this->objFileModule = NULL; +#endif this->havetempdecl = 0; } @@ -1717,6 +1726,9 @@ TemplateInstance::TemplateInstance(Loc l this->semanticdone = 0; this->withsym = NULL; this->nest = 0; +#ifdef IN_GCC + this->objFileModule = NULL; +#endif this->havetempdecl = 1; assert((size_t)tempdecl->scope > 0x10000); @@ -1762,6 +1774,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) @@ -1778,6 +1794,17 @@ void TemplateInstance::semantic(Scope *s #if LOG printf("+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 @@ -1910,16 +1937,54 @@ void TemplateInstance::semantic(Scope *s #if 1 { 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 { + //fprintf(stderr, "\t2: adding %s to module %s\n", tempdecl->toChars(), sc->module->importedFrom->toChars()); //printf("\t2: adding to module %s\n", sc->module->importedFrom->toChars()); a = sc->module->importedFrom->members; +#ifdef IN_GCC + objFileModule = sc->module->importedFrom; +#endif } for (i = 0; 1; i++) { @@ -2000,10 +2065,12 @@ void TemplateInstance::semantic(Scope *s sc2 = scope->push(this); sc2->parent = this; +#ifndef IN_GCC #if _WIN32 __try { #endif +#endif for (int i = 0; i < members->dim; i++) { Dsymbol *s = (Dsymbol *)members->data[i]; @@ -2011,6 +2078,7 @@ void TemplateInstance::semantic(Scope *s s->semantic(sc2); sc2->module->runDeferredSemantic(); } +#ifndef IN_GCC #if _WIN32 } __except (__ehfilter(GetExceptionInformation())) @@ -2020,6 +2088,7 @@ void TemplateInstance::semantic(Scope *s fatal(); } #endif +#endif /* The problem is when to parse the initializer for a variable. * Perhaps VarDeclaration::semantic() should do it like it does diff -uNrp dmd-0.162/src/dmd/tocsym.c gdc-0.19/d/dmd/tocsym.c --- dmd-0.162/src/dmd/tocsym.c 2006-02-11 20:15:02.000000000 +0100 +++ gdc-0.19/d/dmd/tocsym.c 2006-06-02 05:31:29.000000000 +0200 @@ -11,6 +11,7 @@ #include #include #include +#include "gdc_alloca.h" #include "mars.h" #include "module.h" @@ -79,7 +80,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()); assert(0); // BUG: implement return NULL; } @@ -215,7 +216,7 @@ Symbol *VarDeclaration::toSymbol() break; default: - printf("linkage = %d\n", linkage); + fprintf(stderr, "linkage = %d\n", linkage); assert(0); } type_setmangle(&t, m); @@ -317,7 +318,7 @@ Symbol *FuncDeclaration::toSymbol() break; default: - printf("linkage = %d\n", linkage); + fprintf(stderr, "linkage = %d\n", linkage); assert(0); } } diff -uNrp dmd-0.162/src/dmd/todt.c gdc-0.19/d/dmd/todt.c --- dmd-0.162/src/dmd/todt.c 2006-01-03 03:06:30.000000000 +0100 +++ gdc-0.19/d/dmd/todt.c 2006-06-02 05:31:29.000000000 +0200 @@ -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 +*/ + /* 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 @@ -15,12 +21,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" @@ -31,12 +42,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(); @@ -275,8 +288,6 @@ dt_t *ArrayInitializer::toDtBit() dt_t **pdtend; Type *tb = type->toBasetype(); - //printf("ArrayInitializer::toDtBit('%s')\n", toChars()); - Bits databits; Bits initbits; @@ -337,7 +348,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: @@ -395,6 +410,8 @@ dt_t **Expression::toDt(dt_t **pdt) return pdt; } +#ifndef IN_GCC + dt_t **IntegerExp::toDt(dt_t **pdt) { unsigned sz; @@ -438,7 +455,7 @@ dt_t **RealExp::toDt(dt_t **pdt) break; default: - printf("%s\n", toChars()); + fprintf(stderr, "%s\n", toChars()); type->print(); assert(0); break; @@ -485,6 +502,9 @@ dt_t **ComplexExp::toDt(dt_t **pdt) return pdt; } + +#endif + dt_t **NullExp::toDt(dt_t **pdt) { assert(type); @@ -500,14 +520,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, (char *)string); +#else + pdt = dtnwords(pdt, len, string, sz); +#endif if (tsa->dim) { dim = tsa->dim->toInteger(); @@ -520,11 +548,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; @@ -759,8 +791,13 @@ dt_t **TypeSArray::toDt(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-0.162/src/dmd/toobj.c gdc-0.19/d/dmd/toobj.c --- dmd-0.162/src/dmd/toobj.c 2006-06-25 01:54:20.000000000 +0200 +++ gdc-0.19/d/dmd/toobj.c 2006-07-03 16:46:40.000000000 +0200 @@ -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,11 @@ void Module::genmoduleinfo() } /* ================================================================== */ - void Dsymbol::toObjFile() { //printf("Dsymbol::toObjFile('%s')\n", toChars()); // ignore } - /* ================================================================== */ void ClassDeclaration::toObjFile() @@ -845,6 +925,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) @@ -864,6 +945,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 { @@ -912,6 +1005,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 } /* ================================================================== */ diff -uNrp dmd-0.162/src/dmd/total.h gdc-0.19/d/dmd/total.h --- dmd-0.162/src/dmd/total.h 2006-03-07 18:52:50.000000000 +0100 +++ gdc-0.19/d/dmd/total.h 2006-06-02 05:31:29.000000000 +0200 @@ -18,7 +18,7 @@ #include #include #include -#include +//#include #include "root.h" #include "stringtable.h" diff -uNrp dmd-0.162/src/dmd/typinf.c gdc-0.19/d/dmd/typinf.c --- dmd-0.162/src/dmd/typinf.c 2005-05-02 22:16:28.000000000 +0200 +++ gdc-0.19/d/dmd/typinf.c 2006-06-02 05:31:29.000000000 +0200 @@ -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 @@ -27,6 +33,7 @@ #include "aggregate.h" #include +#ifndef IN_GCC #include "cc.h" #include "global.h" #include "oper.h" @@ -36,6 +43,11 @@ #include "cgcv.h" #include "outbuf.h" #include "irstate.h" +#else +#include "symbol.h" +#include "dt.h" +#include "d-dmd-gcc.h" +#endif /******************************************* @@ -530,7 +542,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-0.162/src/phobos/acinclude.m4 gdc-0.19/d/phobos/acinclude.m4 --- dmd-0.162/src/phobos/acinclude.m4 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/d/phobos/acinclude.m4 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,247 @@ +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])]) + +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-0.162/src/phobos/aclocal.m4 gdc-0.19/d/phobos/aclocal.m4 --- dmd-0.162/src/phobos/aclocal.m4 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/etc/c/zlib/adler32.c gdc-0.19/d/phobos/etc/c/zlib/adler32.c --- dmd-0.162/src/phobos/etc/c/zlib/adler32.c 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/etc/c/zlib/adler32.c 2006-06-02 05:31:29.000000000 +0200 @@ -3,7 +3,7 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -/* @(#) $Id$ */ +/* @(#) $Id: adler32.c,v 1.2 2004/09/29 02:26:32 davidfriedman Exp $ */ #define ZLIB_INTERNAL #include "zlib.h" diff -uNrp dmd-0.162/src/phobos/etc/c/zlib/ChangeLog gdc-0.19/d/phobos/etc/c/zlib/ChangeLog --- dmd-0.162/src/phobos/etc/c/zlib/ChangeLog 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/etc/c/zlib/ChangeLog 2006-06-02 05:31:29.000000000 +0200 @@ -466,7 +466,7 @@ Changes in 1.0.6 (19 Jan 1998) - use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) - added makelcc.bat for lcc-win32 (Tom St Denis) - in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) -- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. +- Avoid expanded $Id: ChangeLog,v 1.2 2004/09/29 02:26:32 davidfriedman Exp $. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. - check for unistd.h in configure (for off_t) - remove useless check parameter in inflate_blocks_free - avoid useless assignment of s->check to itself in inflate_blocks_new diff -uNrp dmd-0.162/src/phobos/etc/c/zlib/compress.c gdc-0.19/d/phobos/etc/c/zlib/compress.c --- dmd-0.162/src/phobos/etc/c/zlib/compress.c 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/etc/c/zlib/compress.c 2006-06-02 05:31:29.000000000 +0200 @@ -3,7 +3,7 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -/* @(#) $Id$ */ +/* @(#) $Id: compress.c,v 1.2 2004/09/29 02:26:32 davidfriedman Exp $ */ #define ZLIB_INTERNAL #include "zlib.h" diff -uNrp dmd-0.162/src/phobos/etc/c/zlib/crc32.c gdc-0.19/d/phobos/etc/c/zlib/crc32.c --- dmd-0.162/src/phobos/etc/c/zlib/crc32.c 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/etc/c/zlib/crc32.c 2006-06-02 05:31:29.000000000 +0200 @@ -9,7 +9,7 @@ * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. */ -/* @(#) $Id$ */ +/* @(#) $Id: crc32.c,v 1.2 2004/09/29 02:26:32 davidfriedman Exp $ */ #ifdef MAKECRCH # include diff -uNrp dmd-0.162/src/phobos/etc/c/zlib/deflate.c gdc-0.19/d/phobos/etc/c/zlib/deflate.c --- dmd-0.162/src/phobos/etc/c/zlib/deflate.c 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/etc/c/zlib/deflate.c 2006-06-02 05:31:29.000000000 +0200 @@ -47,7 +47,7 @@ * */ -/* @(#) $Id$ */ +/* @(#) $Id: deflate.c,v 1.2 2004/09/29 02:26:32 davidfriedman Exp $ */ #include "deflate.h" diff -uNrp dmd-0.162/src/phobos/etc/c/zlib/deflate.h gdc-0.19/d/phobos/etc/c/zlib/deflate.h --- dmd-0.162/src/phobos/etc/c/zlib/deflate.h 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/etc/c/zlib/deflate.h 2006-06-02 05:31:29.000000000 +0200 @@ -8,7 +8,7 @@ subject to change. Applications should only use zlib.h. */ -/* @(#) $Id$ */ +/* @(#) $Id: deflate.h,v 1.2 2004/09/29 02:26:32 davidfriedman Exp $ */ #ifndef DEFLATE_H #define DEFLATE_H diff -uNrp dmd-0.162/src/phobos/etc/c/zlib/example.c gdc-0.19/d/phobos/etc/c/zlib/example.c --- dmd-0.162/src/phobos/etc/c/zlib/example.c 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/etc/c/zlib/example.c 2006-06-02 05:31:29.000000000 +0200 @@ -3,7 +3,7 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -/* @(#) $Id$ */ +/* @(#) $Id: example.c,v 1.2 2004/09/29 02:26:32 davidfriedman Exp $ */ #include #include "zlib.h" diff -uNrp dmd-0.162/src/phobos/etc/c/zlib/gzio.c gdc-0.19/d/phobos/etc/c/zlib/gzio.c --- dmd-0.162/src/phobos/etc/c/zlib/gzio.c 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/etc/c/zlib/gzio.c 2006-06-02 05:31:29.000000000 +0200 @@ -5,7 +5,7 @@ * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. */ -/* @(#) $Id$ */ +/* @(#) $Id: gzio.c,v 1.2 2004/09/29 02:26:32 davidfriedman Exp $ */ #include diff -uNrp dmd-0.162/src/phobos/etc/c/zlib/minigzip.c gdc-0.19/d/phobos/etc/c/zlib/minigzip.c --- dmd-0.162/src/phobos/etc/c/zlib/minigzip.c 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/etc/c/zlib/minigzip.c 2006-06-02 05:31:29.000000000 +0200 @@ -13,7 +13,7 @@ * or in pipe mode. */ -/* @(#) $Id$ */ +/* @(#) $Id: minigzip.c,v 1.2 2004/09/29 02:26:32 davidfriedman Exp $ */ #include #include "zlib.h" diff -uNrp dmd-0.162/src/phobos/etc/c/zlib/trees.c gdc-0.19/d/phobos/etc/c/zlib/trees.c --- dmd-0.162/src/phobos/etc/c/zlib/trees.c 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/etc/c/zlib/trees.c 2006-06-02 05:31:29.000000000 +0200 @@ -29,7 +29,7 @@ * Addison-Wesley, 1983. ISBN 0-201-06672-6. */ -/* @(#) $Id$ */ +/* @(#) $Id: trees.c,v 1.2 2004/09/29 02:26:32 davidfriedman Exp $ */ /* #define GEN_TREES_H */ diff -uNrp dmd-0.162/src/phobos/etc/c/zlib/uncompr.c gdc-0.19/d/phobos/etc/c/zlib/uncompr.c --- dmd-0.162/src/phobos/etc/c/zlib/uncompr.c 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/etc/c/zlib/uncompr.c 2006-06-02 05:31:29.000000000 +0200 @@ -3,7 +3,7 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -/* @(#) $Id$ */ +/* @(#) $Id: uncompr.c,v 1.2 2004/09/29 02:26:32 davidfriedman Exp $ */ #define ZLIB_INTERNAL #include "zlib.h" diff -uNrp dmd-0.162/src/phobos/etc/c/zlib/zconf.h gdc-0.19/d/phobos/etc/c/zlib/zconf.h --- dmd-0.162/src/phobos/etc/c/zlib/zconf.h 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/etc/c/zlib/zconf.h 2006-06-02 05:31:29.000000000 +0200 @@ -3,7 +3,7 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -/* @(#) $Id$ */ +/* @(#) $Id: zconf.h,v 1.2 2004/09/29 02:26:32 davidfriedman Exp $ */ #ifndef ZCONF_H #define ZCONF_H diff -uNrp dmd-0.162/src/phobos/etc/c/zlib/zconf.in.h gdc-0.19/d/phobos/etc/c/zlib/zconf.in.h --- dmd-0.162/src/phobos/etc/c/zlib/zconf.in.h 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/etc/c/zlib/zconf.in.h 2006-06-02 05:31:29.000000000 +0200 @@ -3,7 +3,7 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -/* @(#) $Id$ */ +/* @(#) $Id: zconf.in.h,v 1.1 2004/09/29 02:19:34 davidfriedman Exp $ */ #ifndef ZCONF_H #define ZCONF_H diff -uNrp dmd-0.162/src/phobos/etc/c/zlib/zutil.c gdc-0.19/d/phobos/etc/c/zlib/zutil.c --- dmd-0.162/src/phobos/etc/c/zlib/zutil.c 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/etc/c/zlib/zutil.c 2006-06-02 05:31:29.000000000 +0200 @@ -3,7 +3,7 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -/* @(#) $Id$ */ +/* @(#) $Id: zutil.c,v 1.2 2004/09/29 02:26:32 davidfriedman Exp $ */ #include "zutil.h" diff -uNrp dmd-0.162/src/phobos/etc/c/zlib/zutil.h gdc-0.19/d/phobos/etc/c/zlib/zutil.h --- dmd-0.162/src/phobos/etc/c/zlib/zutil.h 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/etc/c/zlib/zutil.h 2006-06-02 05:31:29.000000000 +0200 @@ -8,7 +8,7 @@ subject to change. Applications should only use zlib.h. */ -/* @(#) $Id$ */ +/* @(#) $Id: zutil.h,v 1.2 2004/09/29 02:26:32 davidfriedman Exp $ */ #ifndef ZUTIL_H #define ZUTIL_H diff -uNrp dmd-0.162/src/phobos/etc/gamma.d gdc-0.19/d/phobos/etc/gamma.d --- dmd-0.162/src/phobos/etc/gamma.d 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/etc/gamma.d 2006-06-02 05:31:29.000000000 +0200 @@ -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) { @@ -106,7 +111,7 @@ extern (C) long _adReverseChar(char[] a) hi = hi - 1 + (stridehi - stridelo); } } - return *cast(long*)(&a); + return *cast(Array*)(&a); } unittest @@ -138,7 +143,7 @@ unittest * reversed. */ -extern (C) long _adReverseWchar(wchar[] a) +extern (C) Array _adReverseWchar(wchar[] a) { if (a.length > 1) { @@ -196,7 +201,7 @@ extern (C) long _adReverseWchar(wchar[] hi = hi - 1 + (stridehi - stridelo); } } - return *cast(long*)(&a); + return *cast(Array*)(&a); } unittest @@ -216,15 +221,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 { @@ -263,7 +416,7 @@ extern (C) long _adReverse(Array a, int //delete tmp; } } - return *cast(long*)(&a); + return a; } unittest @@ -408,10 +561,10 @@ unittest * Support for array.dup property. */ -extern (C) long _adDup(Array a, int szelem) +extern (C) Array _adDup(Array a, int szelem) out (result) { - assert(memcmp((*cast(Array*)&result).ptr, a.ptr, a.length * szelem) == 0); + assert(memcmp(result.ptr, a.ptr, a.length * szelem) == 0); } body { @@ -421,7 +574,7 @@ extern (C) long _adDup(Array a, int szel r.ptr = cast(void *) new byte[size]; r.length = a.length; memcpy(r.ptr, a.ptr, size); - return *cast(long*)(&r); + return r; } unittest @@ -444,10 +597,10 @@ unittest * Support for array.dup property for bit[]. */ -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 { @@ -457,7 +610,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 @@ -530,12 +683,12 @@ unittest */ 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++) { @@ -618,151 +771,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-0.162/src/phobos/internal/arraycat.d gdc-0.19/d/phobos/internal/arraycat.d --- dmd-0.162/src/phobos/internal/arraycat.d 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/internal/arraycat.d 2006-06-02 05:31:29.000000000 +0200 @@ -27,33 +27,34 @@ import object; import std.string; import std.c.string; import std.c.stdio; +import std.c.stdarg; 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, b.length * size); diff -uNrp dmd-0.162/src/phobos/internal/cmain.d gdc-0.19/d/phobos/internal/cmain.d --- dmd-0.162/src/phobos/internal/cmain.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/internal/critical.c gdc-0.19/d/phobos/internal/critical.c --- dmd-0.162/src/phobos/internal/critical.c 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/internal/critical.c 2006-06-02 05:31:29.000000000 +0200 @@ -2,6 +2,14 @@ // All Rights Reserved // 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 +*/ + +#include "config.h" + /* ================================= Win32 ============================ */ #if _WIN32 @@ -73,16 +81,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. @@ -115,7 +129,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); } @@ -124,7 +142,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); } @@ -132,8 +150,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-0.162/src/phobos/internal/dgccmain2.d gdc-0.19/d/phobos/internal/dgccmain2.d --- dmd-0.162/src/phobos/internal/dgccmain2.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/d/phobos/internal/dgccmain2.d 2006-06-02 05:31:29.000000000 +0200 @@ -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 = false; + +/*********************************** + * 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 servers 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-0.162/src/phobos/internal/fpmath.d gdc-0.19/d/phobos/internal/fpmath.d --- dmd-0.162/src/phobos/internal/fpmath.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/d/phobos/internal/fpmath.d 2006-06-02 05:31:29.000000000 +0200 @@ -0,0 +1,172 @@ +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 { + 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-0.162/src/phobos/internal/gc/gcbits.d gdc-0.19/d/phobos/internal/gc/gcbits.d --- dmd-0.162/src/phobos/internal/gc/gcbits.d 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/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-0.162/src/phobos/internal/gc/gc_c.h gdc-0.19/d/phobos/internal/gc/gc_c.h --- dmd-0.162/src/phobos/internal/gc/gc_c.h 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/internal/gc/gc.d gdc-0.19/d/phobos/internal/gc/gc.d --- dmd-0.162/src/phobos/internal/gc/gc.d 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/internal/gc/gc.d 2006-07-03 16:46:40.000000000 +0200 @@ -19,8 +19,18 @@ * be misrepresented as being the original software. * o This notice may not be removed or altered from any source * distribution. + * + * Modifications from original software: + * + * 2004-09-24 David Friedman -- Modified to work with the D GCC compiler */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, September 2004 +*/ + // Storage allocation @@ -193,70 +203,90 @@ void _d_delclass(Object *p) } } -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; } - -ulong _d_newarrayi(size_t length, size_t size, ...) +/+ +byte[] _d_new(uint length, uint size) { void *p; - ulong result; - //debug(PRINTF) printf("_d_newarrayi(length = %d, size = %d)\n", length, size); - if (length == 0 || size == 0) - result = 0; - else + debug(PRINTF) printf("_d_newarray(length = %d, size = %d)\n", length, size); + 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); + p = _gc.malloc(length * size); debug(PRINTF) printf(" p = %p\n", p); + memset(p, 0, length * size); + return (cast(byte*)p)[0..length]; + } else + return null; +} ++/ + +Array _d_newarrayip(size_t length, size_t size, void * init) +{ + Array result; + + if (length && size) + { + 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 { + 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; } -ulong _d_newbitarray(size_t length, bit value) + +Array _d_newbitarray(size_t length, bit value) { void *p; - ulong result; + Array result; debug(PRINTF) printf("_d_newbitarray(length = %d, value = %d)\n", length, value); + /* if (length == 0) result = 0; else - { size_t size = (length + 8) >> 3; // number of bytes + */ + if (length) + { size_t size = ((length + 31) >> 5) * 4 + 1; // number of bytes + // (not sure what the extra byte is for...) ubyte fill = value ? 0xFF : 0; p = _gc.malloc(size); debug(PRINTF) printf(" p = %p\n", p); memset(p, fill, size); - result = cast(ulong)length + (cast(ulong)cast(uint)p << 32); + result.length = length; + result.data = cast(byte*)p; } return result; } @@ -361,6 +391,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; @@ -420,7 +458,7 @@ Loverflow: * For non-zero initializers */ 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); @@ -439,6 +477,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; @@ -480,18 +526,15 @@ 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) - 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); } } } @@ -565,7 +608,7 @@ bit[] _d_arraysetlengthb(size_t newlengt */ 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); @@ -580,11 +623,11 @@ long _d_arrayappend(Array *px, byte[] y, } px.length = newlength; memcpy(px.data + length * size, y, y.length * size); - return *cast(long*)px; + return *px; } extern (C) -long _d_arrayappendb(Array *px, bit[] y) +Array _d_arrayappendb(Array *px, bit[] y) { size_t cap = _gc.capacity(px.data); @@ -611,7 +654,7 @@ long _d_arrayappendb(Array *px, bit[] y) x[length + u] = y[u]; } } - return *cast(long*)px; + return *px; } @@ -683,7 +726,7 @@ size_t newCapacity(size_t newlength, siz } 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); size_t length = x.length; @@ -703,10 +746,9 @@ byte[] _d_arrayappendc(inout byte[] x, i memcpy(newdata, x, 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; diff -uNrp dmd-0.162/src/phobos/internal/gc/gc_dyld.c gdc-0.19/d/phobos/internal/gc/gc_dyld.c --- dmd-0.162/src/phobos/internal/gc/gc_dyld.c 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/internal/gc/gc_freebsd.c gdc-0.19/d/phobos/internal/gc/gc_freebsd.c --- dmd-0.162/src/phobos/internal/gc/gc_freebsd.c 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/internal/gc/gcgcc.d gdc-0.19/d/phobos/internal/gc/gcgcc.d --- dmd-0.162/src/phobos/internal/gc/gcgcc.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/internal/gc/gcgccextern.d gdc-0.19/d/phobos/internal/gc/gcgccextern.d --- dmd-0.162/src/phobos/internal/gc/gcgccextern.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/internal/gc/gc_guess_stack.d gdc-0.19/d/phobos/internal/gc/gc_guess_stack.d --- dmd-0.162/src/phobos/internal/gc/gc_guess_stack.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/internal/gc/gcx.d gdc-0.19/d/phobos/internal/gc/gcx.d --- dmd-0.162/src/phobos/internal/gc/gcx.d 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/internal/gc/gcx.d 2006-06-02 05:31:29.000000000 +0200 @@ -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, September 2004 +*/ + // D Garbage Collector implementation /************** Debugging ***************************/ @@ -31,22 +37,33 @@ debug (PRINTF) import std.c.stdio; import std.c.stdio; import std.c.stdlib; -import std.c.string; import gcbits; import std.outofmemory; import std.gc; import gcstats; +version (GNU) +{ + private import gcc.builtins; +} + version (Win32) { import win32; } - -version (linux) +else version (GNU) +{ + private import gcgcc; +} +else version (linux) { import gclinux; } +/*version (BigEndian) + private import std.intrinsic;*/ + + version (MULTI_THREADED) { @@ -56,6 +73,8 @@ version (MULTI_THREADED) //alias GC* gc_t; alias GC gc_t; +version (X86) version (D_InlineAsm) { version = Asm86; } + /* ======================= Leak Detector =========================== */ debug (LOGGING) @@ -182,7 +201,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()); } @@ -290,9 +313,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); } @@ -557,7 +582,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"); } @@ -567,7 +598,13 @@ class GC uint nbytes; os_query_staticdataseg(&pbot, &nbytes); - g.removeRange(pbot); + version (GNU) { + if (pbot) { + g.removeRange(pbot); + } + } else { + g.removeRange(pbot); + } } @@ -953,7 +990,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) { @@ -977,7 +1014,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--;) { @@ -1374,15 +1411,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; } @@ -1451,7 +1503,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()); @@ -1522,6 +1585,9 @@ struct Gcx *b = 0; o = pool.baseAddr + (b - bbase) * 32 * 16; + /* version (BigEndian) + bitm = bswap(bitm); + */ if (!(bitm & 0xFFFF)) { bitm >>= 16; @@ -1765,7 +1831,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-0.162/src/phobos/internal/gc/win32.d gdc-0.19/d/phobos/internal/gc/win32.d --- dmd-0.162/src/phobos/internal/gc/win32.d 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/internal/gc/win32.d 2006-06-02 05:31:29.000000000 +0200 @@ -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-0.162/src/phobos/internal/memset.d gdc-0.19/d/phobos/internal/memset.d --- dmd-0.162/src/phobos/internal/memset.d 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/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-0.162/src/phobos/internal/monitor.c gdc-0.19/d/phobos/internal/monitor.c --- dmd-0.162/src/phobos/internal/monitor.c 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/internal/monitor.c 2006-06-02 05:31:29.000000000 +0200 @@ -1,8 +1,17 @@ + + // Copyright (c) 2000-2004 by Digital Mars // All Rights Reserved // 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, September 2004 +*/ + +#include "config.h" #include @@ -87,14 +96,17 @@ void _d_monitorrelease(Object *h) /* =============================== linux ============================ */ -#if linux - -// Includes attribute fixes from David Friedman's GDC port +// needs to be else.. +#if linux || PHOBOS_USE_PTHREADS #include #include "mars.h" +#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; static volatile int inited; @@ -102,10 +114,12 @@ static volatile int inited; 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; } } @@ -114,8 +128,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 } } @@ -131,7 +147,11 @@ void _d_monitorenter(Object *h) if (!h->monitor) // if, in the meantime, another thread didn't set it { h->monitor = (unsigned)cs; +#ifndef PTHREAD_MUTEX_ALREADY_RECURSIVE pthread_mutex_init(cs, & _monitors_attr); +#else + pthread_mutex_init(cs, NULL); +#endif cs = NULL; } pthread_mutex_unlock(&_monitor_critsec); diff -uNrp dmd-0.162/src/phobos/internal/object.d gdc-0.19/d/phobos/internal/object.d --- dmd-0.162/src/phobos/internal/object.d 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/internal/object.d 2006-06-02 05:31:29.000000000 +0200 @@ -31,6 +31,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; @@ -527,7 +533,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, xsize) == 0); @@ -545,7 +557,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, xsize); diff -uNrp dmd-0.162/src/phobos/internal/qsort.d gdc-0.19/d/phobos/internal/qsort.d --- dmd-0.162/src/phobos/internal/qsort.d 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/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; // 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) // 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-0.162/src/phobos/internal/qsortg.d gdc-0.19/d/phobos/internal/qsortg.d --- dmd-0.162/src/phobos/internal/qsortg.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/d/phobos/internal/qsortg.d 2006-06-02 05:31:29.000000000 +0200 @@ -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; + 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) + { + --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-0.162/src/phobos/internal/rundmain.d gdc-0.19/d/phobos/internal/rundmain.d --- dmd-0.162/src/phobos/internal/rundmain.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/libgphobos.spec.in gdc-0.19/d/phobos/libgphobos.spec.in --- dmd-0.162/src/phobos/libgphobos.spec.in 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/Makefile.in gdc-0.19/d/phobos/Makefile.in --- dmd-0.162/src/phobos/Makefile.in 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/d/phobos/Makefile.in 2006-07-03 00:54:24.000000000 +0200 @@ -0,0 +1,288 @@ +# 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 $< + +%.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 + $(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 + $(GDC) -o $@ $(CFLAGS) internal/gc/testgc.o -L./ -lgphobos_t $(LIBS) + +TI=ti_AC.o ti_Aa.o ti_Adchar.o ti_Ag.o ti_Aint.o ti_Along.o ti_Ashort.o \ + ti_Aubyte.o ti_Auint.o ti_Aulong.o ti_Aushort.o ti_Awchar.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 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/boxer.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 + +# 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: + echo 'Removing files...' + 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-0.162/src/phobos/phobos.d gdc-0.19/d/phobos/phobos.d --- dmd-0.162/src/phobos/phobos.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/phobos.d 1970-01-01 01:00:00.000000000 +0100 @@ -1,283 +0,0 @@ -Ddoc - -Phobos is the standard runtime library that comes with the -D language compiler. Also, check out the -wiki for Phobos. - - -

Philosophy

- - Each module in Phobos conforms as much as possible to the - following design goals. These are goals - rather than requirements because D is not a religion, - it's a programming language, and it recognizes that - sometimes the goals are contradictory and counterproductive - in certain situations, and programmers have - jobs that need to get done. - -
- - -
Machine and Operating System Independent Interfaces - -
It's pretty well accepted that gratuitous non-portability - should be avoided. This should not be - construed, however, as meaning that access to unusual - features of an operating system should be prevented. - - -
Simple Operations should be Simple - -
A common and simple operation, like writing an array of - bytes to a file, should be simple to - code. I haven't seen a class library yet that simply and efficiently - implemented common, basic file I/O operations. - - -
Classes should strive to be independent of one another - -
It's discouraging to pull in a megabyte of code bloat - by just trying to read a file into an array of - bytes. Class independence also means that classes that turn - out to be mistakes can be deprecated and redesigned without - forcing a rewrite of the rest of the class library. - - -
No pointless wrappers around C runtime library functions or OS API functions - -
D provides direct access to C runtime library functions - and operating system API functions. - Pointless D wrappers around those functions just adds blather, - bloat, baggage and bugs. - - -
Class implementations should use DBC - -
This will prove that DBC (Contract Programming) is worthwhile. - Not only will it aid in debugging the class, but - it will help every class user use the class correctly. - DBC in the class library will have great leverage. - - -
Use Exceptions for Error Handling - -
See Error Handling in D. - -
- -
-

Imports

- - Runtime library modules can be imported with the - import statement. Each module falls into one of several - packages: - -
-
std -
These are the core modules. -

- -

-
std.windows -
Modules specific to the Windows operating system. -

- -

std.linux -
Modules specific to the Linux operating system. -

- -

std.c -
Modules that are simply interfaces to C functions. - For example, interfaces to standard C library functions - will be in std.c, such as std.c.stdio would be the interface - to C's stdio.h. -

- -

-
std.c.windows -
Modules corresponding to the C Windows API functions. -

- -

std.c.linux -
Modules corresponding to the C Linux API functions. -

- -

-
- -
- -
-
etc -
This is the root of a hierarchy of modules mirroring the std - hierarchy. Modules in etc are not standard D modules. They are - here because they are experimental, or for some other reason are - not quite suitable for std, although they are still useful. -

-

- -
-

std: Core library modules

- -
- -
std.base64 -
Encode/decode base64 format. - -
std.boxer -
Box/unbox types. - -
std.compiler -
Information about the D compiler implementation. - -
std.conv -
Conversion of strings to integers. - -
std.ctype -
Simple character classification - -
std.date -
Date and time functions. Support locales. - -
std.file -
Basic file operations like read, write, append. - -
std.format -
Formatted conversions of values to strings. - -
std.gc -
Control the garbage collector. - -
std.intrinsic -
Compiler built in intrinsic functions - -
std.math -
Include all the usual math functions like sin, cos, atan, etc. - -
std.md5 -
Compute MD5 digests. - -
std.mmfile -
Memory mapped files. - -
object -
The root class of the inheritance hierarchy - -
std.openrj -
Basic database. - -
std.outbuffer -
Assemble data into an array of bytes - -
std.path -
Manipulate file names, path names, etc. - -
std.process -
Create/destroy threads. - -
std.random -
Random number generation. - -
std.recls -
Recursively search file system and (currently Windows - only) FTP sites. - -
std.regexp -
The usual regular expression functions. - -
std.socket -
Sockets. - -
std.socketstream -
Stream for a blocking, connected Socket. - -
std.stdint -
Integral types for various purposes. - -
std.stdio -
Standard I/O. - -
std.cstream -
Stream I/O. - -
std.stream -
Stream I/O. - -
std.string -
Basic string operations not covered by array ops. - -
std.system -
Inquire about the CPU, operating system. - -
std.thread -
One per thread. Operations to do on a thread. - -
std.uri -
Encode and decode Uniform Resource Identifiers (URIs). - -
std.utf -
Encode and decode utf character encodings. - -
std.zip -
Read/write zip archives. - -
std.zlib -
Compression / Decompression of data. - -
- -
-

std.windows: Modules specific to the Windows operating system

- -
- -
std.windows.syserror -
Convert Windows error codes to strings. - -
- -
-

std.linux: Modules specific to the Linux operating system

- -
-

std.c: Interface to C functions

- -
- -
std.c.stdio -
Interface to C stdio functions like printf(). - -
- -
-

std.c.windows: Interface to C Windows functions

- -
- -
std.c.windows.windows -
Interface to Windows APIs - -
- -
-

std.c.linux: Interface to C Linux functions

- -
- -
std.c.linux.linux -
Interface to Linux APIs - -
- -
-

std.c.stdio

- -
-
int printf(char* format, ...) -
C printf() function. -
- -Macros: - TITLE=Phobos Runtime Library - WIKI=Phobos - diff -uNrp dmd-0.162/src/phobos/phobos-ver-syms.in gdc-0.19/d/phobos/phobos-ver-syms.in --- dmd-0.162/src/phobos/phobos-ver-syms.in 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/std/bitarray.d gdc-0.19/d/phobos/std/bitarray.d --- dmd-0.162/src/phobos/std/bitarray.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/bitarray.d 2006-06-21 05:12:11.000000000 +0200 @@ -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-0.162/src/phobos/std/boxer.d gdc-0.19/d/phobos/std/boxer.d --- dmd-0.162/src/phobos/std/boxer.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/boxer.d 2006-06-21 05:12:11.000000000 +0200 @@ -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); + version (GNU) + { + va_list dummy = void; + std.format.doFormat(&putc, arguments, dummy, args); + } + else + std.format.doFormat(&putc, arguments, args); delete args; return string; @@ -400,7 +421,25 @@ in } body { - return box(_arguments[0], _argptr); + version (GNU) + { + void * p; + version (BigEndian) + { + byte b; + short s; + switch (_arguments[0].tsize()) { + case 1: b = va_arg!(byte)(_argptr); p = & b; break; + case 2: s = va_arg!(short)(_argptr); p = & s; break; + default: p = cast(void *) _argptr; + } + } + else + p = cast(void *) _argptr; + return box(_arguments[0], p); + } + else + return box(_arguments[0], _argptr); } /** @@ -449,17 +488,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; diff -uNrp dmd-0.162/src/phobos/std/c/darwin/darwin.d gdc-0.19/d/phobos/std/c/darwin/darwin.d --- dmd-0.162/src/phobos/std/c/darwin/darwin.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/std/c/darwin/ldblcompat.d gdc-0.19/d/phobos/std/c/darwin/ldblcompat.d --- dmd-0.162/src/phobos/std/c/darwin/ldblcompat.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/std/c/dirent.d gdc-0.19/d/phobos/std/c/dirent.d --- dmd-0.162/src/phobos/std/c/dirent.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/d/phobos/std/c/dirent.d 2006-06-02 05:31:29.000000000 +0200 @@ -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); + else + return null; +} diff -uNrp dmd-0.162/src/phobos/std/c/linux/ldblcompat.d gdc-0.19/d/phobos/std/c/linux/ldblcompat.d --- dmd-0.162/src/phobos/std/c/linux/ldblcompat.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/std/c/linux/linux.d gdc-0.19/d/phobos/std/c/linux/linux.d --- dmd-0.162/src/phobos/std/c/linux/linux.d 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/std/c/linux/linux.d 2006-06-02 05:31:29.000000000 +0200 @@ -1,355 +1,11 @@ - -/* 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; +import std.c.unix.unix; +import std.c.dirent; import std.c.linux.linuxextern; -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; - ushort __pad1; - uint st_ino; - uint st_mode; - uint st_nlink; - uint st_uid; - uint st_gid; - ulong st_rdev; - ushort __pad2; - int st_size; - int st_blksize; - int st_blocks; - int st_atime; - uint __unused1; - int st_mtime; - uint __unused2; - int st_ctime; - uint __unused3; - 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 -} - -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); -} - -struct timeval -{ - int tv_sec; - int tv_usec; -} - -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*, void*); - int time(int*); - tm *localtime(int*); -} - -/**************************************************************/ -// 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 @@ -363,134 +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; - } - - int getpwnam_r(char*, passwd*, void*, size_t, passwd**); -} - -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 - */ - - 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 - */ - - 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*); -} - -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*); -} - diff -uNrp dmd-0.162/src/phobos/std/c/linux/linux.d.orig-dmd gdc-0.19/d/phobos/std/c/linux/linux.d.orig-dmd --- dmd-0.162/src/phobos/std/c/linux/linux.d.orig-dmd 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/d/phobos/std/c/linux/linux.d.orig-dmd 2006-06-04 17:00:50.000000000 +0200 @@ -0,0 +1,496 @@ + +/* 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; + +import std.c.linux.linuxextern; + +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; + ushort __pad1; + uint st_ino; + uint st_mode; + uint st_nlink; + uint st_uid; + uint st_gid; + ulong st_rdev; + ushort __pad2; + int st_size; + int st_blksize; + int st_blocks; + int st_atime; + uint __unused1; + int st_mtime; + uint __unused2; + int st_ctime; + uint __unused3; + 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 +} + +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); +} + +struct timeval +{ + int tv_sec; + int tv_usec; +} + +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*, void*); + int time(int*); + tm *localtime(int*); +} + +/**************************************************************/ +// 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; + } + + int getpwnam_r(char*, passwd*, void*, size_t, passwd**); +} + +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 + */ + + 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 + */ + + 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*); +} + +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*); +} + diff -uNrp dmd-0.162/src/phobos/std/c/mach/mach.d gdc-0.19/d/phobos/std/c/mach/mach.d --- dmd-0.162/src/phobos/std/c/mach/mach.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/std/c/mach/mach_extern.d gdc-0.19/d/phobos/std/c/mach/mach_extern.d --- dmd-0.162/src/phobos/std/c/mach/mach_extern.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/std/c/math.d gdc-0.19/d/phobos/std/c/math.d --- dmd-0.162/src/phobos/std/c/math.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/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-0.162/src/phobos/std/c/skyos/compat.d gdc-0.19/d/phobos/std/c/skyos/compat.d --- dmd-0.162/src/phobos/std/c/skyos/compat.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/std/c/skyos/skyos.d gdc-0.19/d/phobos/std/c/skyos/skyos.d --- dmd-0.162/src/phobos/std/c/skyos/skyos.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/std/c/stdarg.d gdc-0.19/d/phobos/std/c/stdarg.d --- dmd-0.162/src/phobos/std/c/stdarg.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/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-0.162/src/phobos/std/c/stddef.d gdc-0.19/d/phobos/std/c/stddef.d --- dmd-0.162/src/phobos/std/c/stddef.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/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-0.162/src/phobos/std/c/stdio.d gdc-0.19/d/phobos/std/c/stdio.d --- dmd-0.162/src/phobos/std/c/stdio.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/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-0.162/src/phobos/std/c/stdlib.d gdc-0.19/d/phobos/std/c/stdlib.d --- dmd-0.162/src/phobos/std/c/stdlib.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/c/stdlib.d 2006-06-02 05:31:29.000000000 +0200 @@ -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; @@ -40,22 +46,34 @@ struct lldiv_t { long quot,rem; } void exit(int); /// ditto void _exit(int); /// ditto - 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 @@ -71,15 +89,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-0.162/src/phobos/std/c/string.d gdc-0.19/d/phobos/std/c/string.d --- dmd-0.162/src/phobos/std/c/string.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/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-0.162/src/phobos/std/c/time.d gdc-0.19/d/phobos/std/c/time.d --- dmd-0.162/src/phobos/std/c/time.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/c/time.d 2006-06-02 05:31:29.000000000 +0200 @@ -16,6 +16,11 @@ extern (C): version (Windows) { const uint CLOCKS_PER_SEC = 1000; } +else version (GNU) +{ + private import gcc.config; + alias gcc.config.CLOCKS_PER_SEC CLOCKS_PER_SEC; +} else version (linux) { const uint CLOCKS_PER_SEC = 1000000; } diff -uNrp dmd-0.162/src/phobos/std/c/unix/unix.d gdc-0.19/d/phobos/std/c/unix/unix.d --- dmd-0.162/src/phobos/std/c/unix/unix.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/d/phobos/std/c/unix/unix.d 2006-06-02 05:31:29.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. */ + +import gcc.configunix; + +// DMD linux.d has dirent.h declarations +import std.c.dirent; diff -uNrp dmd-0.162/src/phobos/std/conv.d gdc-0.19/d/phobos/std/conv.d --- dmd-0.162/src/phobos/std/conv.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/conv.d 2006-06-21 05:12:11.000000000 +0200 @@ -869,6 +869,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; @@ -876,6 +888,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; @@ -886,7 +900,7 @@ float toFloat(in char[] s) f = strtof(sz, &endptr); if (getErrno() == ERANGE) goto Lerr; - if (endptr && (endptr == s || *endptr != 0)) + if (endptr && (endptr == sz || *endptr != 0)) goto Lerr; return f; @@ -940,6 +954,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; @@ -950,7 +966,7 @@ double toDouble(in char[] s) f = strtod(sz, &endptr); if (getErrno() == ERANGE) goto Lerr; - if (endptr && (endptr == s || *endptr != 0)) + if (endptr && (endptr == sz || *endptr != 0)) goto Lerr; return f; @@ -1006,6 +1022,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; @@ -1013,10 +1031,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 || *endptr != 0)) + if (endptr && (endptr == sz || *endptr != 0)) goto Lerr; return f; @@ -1216,11 +1234,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)); @@ -1295,11 +1313,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)); @@ -1370,11 +1388,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-0.162/src/phobos/std/date.d gdc-0.19/d/phobos/std/date.d --- dmd-0.162/src/phobos/std/date.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/date.d 2006-06-21 05:12:11.000000000 +0200 @@ -15,6 +15,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; @@ -509,7 +515,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); @@ -573,7 +579,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); @@ -818,7 +824,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; + int t; + int dst = 0; + + if (dt != d_time_nan) + { + d_time seconds = dt / TicksPerSecond; + t = cast(int) 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; @@ -872,7 +969,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-0.162/src/phobos/std/demangle.d gdc-0.19/d/phobos/std/demangle.d --- dmd-0.162/src/phobos/std/demangle.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/demangle.d 2006-06-21 05:12:11.000000000 +0200 @@ -1,3 +1,8 @@ +/* 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: @@ -329,9 +334,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) @@ -474,8 +479,12 @@ unittest [ "_D4test34__T3barVG3uw3_616263VG3wd3_646566Z1xi", "int test.bar!(wchar[3] \"abc\"w, dchar[3] \"def\"d).x" ], ]; - 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-0.162/src/phobos/std/file.d gdc-0.19/d/phobos/std/file.d --- dmd-0.162/src/phobos/std/file.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/file.d 2006-06-21 05:12:11.000000000 +0200 @@ -23,12 +23,20 @@ * be misrepresented as being the original software. * 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, 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; @@ -805,11 +813,14 @@ void copy(char[] from, char[] to) /* =========================== linux ======================= */ -version (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); @@ -855,7 +866,7 @@ void[] read(char[] name) namez = toStringz(name); //printf("file.read('%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()); @@ -863,7 +874,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; @@ -871,14 +882,14 @@ void[] read(char[] name) size = statbuf.st_size; buf = new byte[size]; - 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; @@ -887,7 +898,7 @@ void[] read(char[] name) return buf; err2: - std.c.linux.linux.close(fd); + unix.close(fd); err: delete buf; @@ -908,21 +919,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, buffer.length); + numwritten = unix.write(fd, buffer, 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()); } @@ -939,21 +950,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, buffer.length); + numwritten = unix.write(fd, buffer, 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()); } @@ -997,7 +1008,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()); @@ -1005,14 +1016,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; @@ -1021,7 +1032,7 @@ ulong getSize(char[] name) return size; err2: - std.c.linux.linux.close(fd); + unix.close(fd); err: err1: throw new FileException(name, getErrno()); @@ -1038,7 +1049,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()); } @@ -1059,7 +1070,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; } @@ -1096,7 +1107,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()); } @@ -1108,7 +1119,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()); } @@ -1120,7 +1131,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()); } @@ -1131,19 +1142,34 @@ void rmdir(char[] pathname) */ char[] getcwd() -{ char* p; - - p = std.c.linux.linux.getcwd(null, 0); +{ + version(all) + { + char buf[PATH_MAX]; + if (! unix.getcwd(buf, buf.length)) + { + throw new FileException("cannot get cwd", getErrno()); + } + size_t len = strlen(buf); + char[] result = new char[len]; + result[] = buf[0..len]; + return result; + } + else + { + char* p; + p = unix.getcwd(null, 0); if (!p) { throw new FileException("cannot get cwd", getErrno()); } - size_t len = std.string.strlen(p); char[] buf = new char[len]; buf[] = p[0 .. len]; std.c.stdlib.free(p); return buf; + } + } /*************************************************** @@ -1157,24 +1183,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); 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() @@ -1216,7 +1262,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; @@ -1225,7 +1271,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; } } diff -uNrp dmd-0.162/src/phobos/std/format.d gdc-0.19/d/phobos/std/format.d --- dmd-0.162/src/phobos/std/format.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/format.d 2006-06-21 05:12:11.000000000 +0200 @@ -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, sl, format, field_width, precision, v); + version (GNU_MinGW_MSVCRT) + n = snprintf(fbuf, sl, format, field_width, precision, cast(double) v); + else + n = snprintf(fbuf, sl, format, 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: @@ -700,7 +714,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)) @@ -714,14 +728,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; @@ -792,6 +814,194 @@ void doFormat(void delegate(dchar) putc, 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; + + default: + goto Lerror; + } + } Lnumber: switch (fc) @@ -941,6 +1151,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: @@ -961,6 +1172,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++]; @@ -997,7 +1232,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 != '%') @@ -1099,6 +1340,9 @@ Lerror: /* ======================== Unit Tests ====================================== */ +version (skyos) + version = no_hexfloat; + unittest { int i; @@ -1114,10 +1358,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-0.162/src/phobos/std/intrinsic.d gdc-0.19/d/phobos/std/intrinsic.d --- dmd-0.162/src/phobos/std/intrinsic.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/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-0.162/src/phobos/std/loader.d gdc-0.19/d/phobos/std/loader.d --- dmd-0.162/src/phobos/std/loader.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/loader.d 2006-06-11 20:57:00.000000000 +0200 @@ -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"; + 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-0.162/src/phobos/std/math2.d gdc-0.19/d/phobos/std/math2.d --- dmd-0.162/src/phobos/std/math2.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/math2.d 2006-06-21 05:12:11.000000000 +0200 @@ -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; } @@ -930,6 +978,18 @@ char[] toString(real x) psize *= 2; p = cast(char*) alloca(psize); } + else version(GNU) + { + // %% Lg on dawrin? + count = std.c.stdio.snprintf(p, psize, "%Lg", x); + if (count == -1) + psize *= 2; + else if (count >= psize) + psize = count + 1; + else + break; + p = cast(char*) alloca(psize); + } else version(linux) { count = snprintf(p, psize, "%Lg", x); diff -uNrp dmd-0.162/src/phobos/std/math.d gdc-0.19/d/phobos/std/math.d --- dmd-0.162/src/phobos/std/math.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/math.d 2006-06-21 05:12:11.000000000 +0200 @@ -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 @@ -289,6 +307,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); @@ -489,7 +513,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 @@ -497,7 +521,7 @@ unittest assert(isPosZero(atanh(0.0))); assert(isNegZero(atanh(-0.0))); assert(isnan(atanh(real.nan))); - assert(isNegZero(atanh(-real.infinity))); + //assert(isNegZero(atanh(-real.infinity))); } /***************************************** @@ -528,8 +552,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) @@ -592,6 +619,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); } /****************************************** @@ -609,6 +637,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); } @@ -633,6 +662,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; @@ -680,6 +711,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; + } + } } @@ -710,6 +758,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]; @@ -747,6 +797,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 */ /************************************** @@ -803,6 +854,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); } /***************************************** @@ -881,6 +933,7 @@ real cbrt(real x) { return std.c.math.c * ±∞ +∞ * ) */ +version (GNU) alias gcc.config.fabsl fabs; else real fabs(real x); /* intrinsic */ @@ -992,6 +1045,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]; @@ -1009,6 +1065,7 @@ unittest * * error function */ +version (GNU_msvcrt_math) { /* nothing */ } else real erf(real x) { return std.c.math.erfl(x); } /********************************** @@ -1016,6 +1073,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); } /*********************************** @@ -1066,6 +1124,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); @@ -1092,6 +1156,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); } /********************************** @@ -1102,6 +1171,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 */ /*************************************** @@ -1121,6 +1191,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); } /********************************************** @@ -1142,6 +1244,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); } /**************************************************** @@ -1178,6 +1298,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; @@ -1186,6 +1307,8 @@ int isnan(real e) return (pe[4] & 0x7FFF) == 0x7FFF && *ps & 0x7FFFFFFFFFFFFFFF; } +else version(GNU) + alias gcc.config.isnan isnan; unittest { @@ -1201,12 +1324,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 { @@ -1224,6 +1350,7 @@ unittest * be converted to normal reals. */ +version (X86) int isnormal(float x) { uint *p = cast(uint *)&x; @@ -1233,9 +1360,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; @@ -1244,9 +1374,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; @@ -1254,6 +1386,7 @@ int isnormal(real e) return (pe[4] & 0x7FFF) != 0x7FFF && *ps < 0; } +else version(GNU) { /* nothing, handled above */ } unittest { @@ -1275,6 +1408,7 @@ unittest * be converted to normal reals. */ +version (X86) int issubnormal(float f) { uint *p = cast(uint *)&f; @@ -1282,6 +1416,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 { @@ -1293,12 +1429,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 { @@ -1310,6 +1448,7 @@ unittest /// ditto +version (X86) int issubnormal(real e) { ushort* pe = cast(ushort *)&e; @@ -1317,6 +1456,7 @@ int issubnormal(real e) return (pe[4] & 0x7FFF) == 0 && *ps > 0; } +else version(GNU) { /* nothing, handled above */ } unittest { @@ -1330,6 +1470,7 @@ unittest * Return !=0 if e is ±∞. */ +version (X86) int isinf(real e) { ushort* pe = cast(ushort *)&e; @@ -1338,7 +1479,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)); @@ -1353,6 +1496,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; @@ -1360,6 +1504,8 @@ int signbit(real e) //printf("e = %Lg\n", e); return (pe[9] & 0x80) != 0; } +else version (GNU) + alias gcc.config.signbit signbit; unittest { @@ -1376,6 +1522,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; @@ -1386,6 +1533,8 @@ real copysign(real to, real from) return to; } +else version (GNU) + alias gcc.config.copysignl copysign; unittest { @@ -1410,6 +1559,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)); } /****************************************** @@ -1553,7 +1705,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 real.nan; @@ -1688,6 +1841,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? * @@ -1787,7 +1944,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³ ... * @@ -1802,63 +1974,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-0.162/src/phobos/std/md5.d gdc-0.19/d/phobos/std/md5.d --- dmd-0.162/src/phobos/std/md5.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/md5.d 2006-06-02 05:31:29.000000000 +0200 @@ -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-0.162/src/phobos/std/mmfile.d gdc-0.19/d/phobos/std/mmfile.d --- dmd-0.162/src/phobos/std/mmfile.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/mmfile.d 2006-06-21 05:12:11.000000000 +0200 @@ -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, 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) == 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-0.162/src/phobos/std/moduleinit.d gdc-0.19/d/phobos/std/moduleinit.d --- dmd-0.162/src/phobos/std/moduleinit.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/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-0.162/src/phobos/std/outbuffer.d gdc-0.19/d/phobos/std/outbuffer.d --- dmd-0.162/src/phobos/std/outbuffer.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/outbuffer.d 2006-06-02 05:31:29.000000000 +0200 @@ -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 @@ -243,23 +249,35 @@ class OutBuffer char* f; uint psize; int count; + va_list args_copy; f = toStringz(format); p = buffer; 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) @@ -290,10 +308,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-0.162/src/phobos/std/path.d gdc-0.19/d/phobos/std/path.d --- dmd-0.162/src/phobos/std/path.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/path.d 2006-06-02 05:31:29.000000000 +0200 @@ -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", "*")); @@ -1010,7 +1027,7 @@ unittest char[] expandTilde(char[] inputPath) { - version(linux) + version(Unix) { static assert(sep.length == 1); @@ -1039,7 +1056,7 @@ unittest { debug(path) printf("path.expandTilde.unittest\n"); - version (linux) + version (Unix) { // Retrieve the current home variable. char* c_home = getenv("HOME"); @@ -1068,13 +1085,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) { /** @@ -1148,6 +1167,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; @@ -1162,7 +1184,7 @@ private char[] expandFromDatabase(char[] // Obtain info from database. passwd *verify; std.c.stdlib.setErrno(0); - if (getpwnam_r(username, &result, extra_memory, extra_memory_size, + if (getpwnam_r(username, &result, cast(char*) extra_memory, extra_memory_size, &verify) == 0) { // Failure if verify doesn't point at result. @@ -1172,8 +1194,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); @@ -1192,6 +1225,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-0.162/src/phobos/std/perf.d gdc-0.19/d/phobos/std/perf.d --- dmd-0.162/src/phobos/std/perf.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/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-0.162/src/phobos/std/process.d gdc-0.19/d/phobos/std/process.d --- dmd-0.162/src/phobos/std/process.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/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-0.162/src/phobos/std/random.d gdc-0.19/d/phobos/std/random.d --- dmd-0.162/src/phobos/std/random.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/random.d 2006-06-21 05:12:11.000000000 +0200 @@ -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; } @@ -95,7 +105,7 @@ static this() { QueryPerformanceCounter(&s); } - version(linux) + else version(Unix) { // time.h // sys/time.h diff -uNrp dmd-0.162/src/phobos/std/regexp.d gdc-0.19/d/phobos/std/regexp.d --- dmd-0.162/src/phobos/std/regexp.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/regexp.d 2006-07-03 00:54:24.000000000 +0200 @@ -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. @@ -140,6 +146,7 @@ private import std.ctype; import std.outbuffer; import std.bitarray; + 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-0.162/src/phobos/std/socket.d gdc-0.19/d/phobos/std/socket.d --- dmd-0.162/src/phobos/std/socket.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/socket.d 2006-06-21 05:12:11.000000000 +0200 @@ -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; @@ -89,7 +103,7 @@ class SocketException: Exception { errorCode = err; - version(linux) + version(Unix) { if(errorCode > 0) { @@ -232,12 +246,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; } } @@ -324,12 +343,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; } @@ -337,12 +361,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; } } @@ -830,7 +859,14 @@ class SocketSet else version(BsdSockets) { maxfd = -1; - buf[0 .. nbytes] = 0; + version(GNU) + { + FD_ZERO(_fd_set); + } + else + { + buf[0 .. nbytes] = 0; + } } } @@ -845,7 +881,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 @@ -943,9 +987,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) { @@ -954,8 +1005,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 @@ -1140,7 +1201,7 @@ class Socket if(WSAEWOULDBLOCK == err) return; } - else version(linux) + else version(Unix) { if(EINPROGRESS == err) return; @@ -1474,12 +1535,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 @@ -1540,7 +1601,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-0.162/src/phobos/std/stdarg.d gdc-0.19/d/phobos/std/stdarg.d --- dmd-0.162/src/phobos/std/stdarg.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/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-0.162/src/phobos/std/stdio.d gdc-0.19/d/phobos/std/stdio.d --- dmd-0.162/src/phobos/std/stdio.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/stdio.d 2006-06-02 05:31:29.000000000 +0200 @@ -4,6 +4,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, September 2004 +*/ + /******************************** * Standard I/O functions that extend $(B std.c.stdio). * $(B std.c.stdio) is automatically imported when importing @@ -48,10 +54,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 @@ -83,6 +90,9 @@ void writefx(FILE* fp, TypeInfo[] argume } else if (orientation > 0) // wide orientation { + version (GNU_Have_fwide) + { + version (Windows) { void putcw(dchar c) @@ -102,7 +112,7 @@ void writefx(FILE* fp, TypeInfo[] argume } } } - else version (linux) + else version (Unix) { void putcw(dchar c) { @@ -117,6 +127,8 @@ void writefx(FILE* fp, TypeInfo[] argume std.format.doFormat(&putcw, arguments, argptr); if (newline) FPUTWC('\n', fp); + + } } } finally diff -uNrp dmd-0.162/src/phobos/std/stream.d gdc-0.19/d/phobos/std/stream.d --- dmd-0.162/src/phobos/std/stream.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/stream.d 2006-06-21 05:12:11.000000000 +0200 @@ -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: @@ -182,7 +188,6 @@ interface InputStream { wchar[] readStringW(size_t length); - /*** * Read and return the next character in the stream. * @@ -191,6 +196,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 @@ -223,7 +230,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. @@ -342,14 +349,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. * @@ -676,7 +682,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; @@ -1122,15 +1128,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) @@ -1148,10 +1156,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) { @@ -1172,7 +1184,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(""); @@ -1771,8 +1783,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; } @@ -1782,7 +1794,7 @@ class File: Stream { version (Win32) { private HANDLE hFile; } - version (linux) { + version (Unix) { private HANDLE hFile = -1; } @@ -1791,7 +1803,7 @@ class File: Stream { version (Win32) { hFile = null; } - version (linux) { + version (Unix) { hFile = -1; } isopen = false; @@ -1848,8 +1860,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) @@ -1876,7 +1888,7 @@ class File: Stream { createMode = CREATE_ALWAYS; // resets file } } - version (linux) { + version (Unix) { if (mode & FileMode.In) { access = O_RDONLY; share = 0660; @@ -1914,8 +1926,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; } } @@ -1939,8 +1951,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; } @@ -1952,8 +1964,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; } @@ -1968,8 +1980,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"); } @@ -2008,7 +2020,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()); @@ -2028,7 +2040,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); @@ -2036,7 +2048,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()); @@ -2125,7 +2137,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()); @@ -2145,7 +2157,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); @@ -2153,7 +2165,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-0.162/src/phobos/std/string.d gdc-0.19/d/phobos/std/string.d --- dmd-0.162/src/phobos/std/string.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/string.d 2006-06-21 05:12:11.000000000 +0200 @@ -23,6 +23,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 @@ -40,11 +46,11 @@ private import std.stdarg; extern (C) { - int wcslen(wchar *); int wcscmp(wchar *, wchar *); } + /* ************* Exceptions *************** */ /// Thrown on errors in string functions. @@ -73,7 +79,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[2] newline = "\n"; /********************************** @@ -146,7 +152,7 @@ int icmp(char[] s1, char[] s2) { result = memicmp(s1, s2, len); } - version (linux) + version (Unix) { for (size_t i = 0; i < len; i++) { @@ -818,7 +824,7 @@ char[] tolower(char[] s) if ('A' <= c && c <= 'Z') { if (!changed) - { r = s.dup; + { r = s.dup; changed = 1; } r[i] = c + (cast(char)'a' - 'A'); @@ -1376,7 +1382,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) @@ -2454,11 +2459,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; - sprintf(buffer, "%Lg", r); + sprintf(buffer, "%"~_longDoubleFormat~"g", r); return std.string.toString(buffer).dup; } @@ -2479,7 +2489,7 @@ char[] toString(ireal r) { char[21] buffer; - sprintf(buffer, "%Lgi", r); + sprintf(buffer, "%"~_longDoubleFormat~"gi", r); return std.string.toString(buffer).dup; } @@ -2500,11 +2510,10 @@ char[] toString(creal r) { char[20 + 1 + 20 + 1] buffer; - sprintf(buffer, "%Lg+%Lgi", r.re, r.im); + sprintf(buffer, "%"~_longDoubleFormat~"g+%"~_longDoubleFormat~"gi", r.re, r.im); return std.string.toString(buffer).dup; } - /****************************************** * Convert value to string in _radix radix. * diff -uNrp dmd-0.162/src/phobos/std/system.d gdc-0.19/d/phobos/std/system.d --- dmd-0.162/src/phobos/std/system.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/system.d 2006-06-02 05:31:29.000000000 +0200 @@ -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-0.162/src/phobos/std/thread.d gdc-0.19/d/phobos/std/thread.d --- dmd-0.162/src/phobos/std/thread.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/thread.d 2006-06-21 05:12:11.000000000 +0200 @@ -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, September 2004 +*/ + /************************** * 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); } @@ -684,6 +644,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); @@ -781,7 +743,7 @@ class Thread Thread result; //printf("getThis(), allThreadsDim = %d\n", allThreadsDim); - synchronized (threadLock) + //synchronized (threadLock) { id = pthread_self(); //printf("id = %d\n", id); @@ -808,13 +770,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"); @@ -823,11 +793,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"); @@ -835,11 +813,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; @@ -855,12 +859,16 @@ class Thread } } + } + // Wait for each paused thread to acknowledge while (npause--) { - sem_wait(&flagSuspend); + flagSuspend.wait(); } } + + } } static void resumeAll() @@ -890,13 +898,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[] @@ -950,6 +965,9 @@ class Thread // before pthread_create() sets it. t.id = pthread_self(); + version(skyos) + installSignalHandlers(); + t.stackBottom = getESP(); try { @@ -965,10 +983,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; } @@ -985,118 +1006,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; + } } 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-0.162/src/phobos/std/typeinfo/ti_Abit.d gdc-0.19/d/phobos/std/typeinfo/ti_Abit.d --- dmd-0.162/src/phobos/std/typeinfo/ti_Abit.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/std/typeinfo/ti_bit.d gdc-0.19/d/phobos/std/typeinfo/ti_bit.d --- dmd-0.162/src/phobos/std/typeinfo/ti_bit.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.19/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-0.162/src/phobos/std/uri.d gdc-0.19/d/phobos/std/uri.d --- dmd-0.162/src/phobos/std/uri.d 2006-06-30 17:13:54.000000000 +0200 +++ gdc-0.19/d/phobos/std/uri.d 2006-06-21 05:12:11.000000000 +0200 @@ -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-0.162/src/phobos/std/windows/registry.d gdc-0.19/d/phobos/std/windows/registry.d --- dmd-0.162/src/phobos/std/windows/registry.d 2006-06-30 17:13:56.000000000 +0200 +++ gdc-0.19/d/phobos/std/windows/registry.d 2006-06-21 05:12:11.000000000 +0200 @@ -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