diff -uNr dmd-0.139/dmd/src/dmd/attrib.c dmd-0.140/dmd/src/dmd/attrib.c --- dmd-0.139/dmd/src/dmd/attrib.c 2005-09-24 00:31:22.000000000 +0200 +++ dmd-0.140/dmd/src/dmd/attrib.c 2005-11-16 15:11:30.000000000 +0100 @@ -752,6 +752,14 @@ Dsymbol *ConditionalDeclaration::oneMember() { + if (condition->inc) + { + Array *d = condition->include(NULL, NULL) ? decl : elsedecl; + if (d && d->dim == 1) + { Dsymbol *s = (Dsymbol *)d->data[0]; + return s->oneMember(); + } + } return NULL; } diff -uNr dmd-0.139/dmd/src/dmd/cast.c dmd-0.140/dmd/src/dmd/cast.c --- dmd-0.139/dmd/src/dmd/cast.c 2005-04-09 00:45:40.000000000 +0200 +++ dmd-0.140/dmd/src/dmd/cast.c 2005-11-24 01:04:34.000000000 +0100 @@ -433,9 +433,12 @@ e = new AddrExp(loc, e); } else + { e = new CastExp(loc, e, tb); + } } e->type = t; + //printf("Returning: %s\n", e->toChars()); return e; } @@ -698,7 +701,6 @@ } e = Expression::castTo(t); } - e->type = t; return e; } diff -uNr dmd-0.139/dmd/src/dmd/constfold.c dmd-0.140/dmd/src/dmd/constfold.c --- dmd-0.139/dmd/src/dmd/constfold.c 2005-10-11 11:44:44.000000000 +0200 +++ dmd-0.140/dmd/src/dmd/constfold.c 2005-11-24 01:02:22.000000000 +0100 @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2004 by Digital Mars +// Copyright (c) 1999-2005 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com @@ -40,11 +40,6 @@ return 1; } -int ImaginaryExp::isConst() -{ - return 1; -} - int ComplexExp::isConst() { return 1; @@ -72,9 +67,9 @@ return e; } else if (e1->type->isimaginary()) - { ImaginaryExp *e; + { RealExp *e; - e = new ImaginaryExp(loc, -e1->toImaginary(), type); + e = new RealExp(loc, -e1->toImaginary(), type); return e; } else if (e1->type->iscomplex()) @@ -110,13 +105,14 @@ //printf("CastExp::constFold(%s)\n", toChars()); e1 = e1->constFold(); - if (e1->op == TOKsymoff && type->size() == e1->type->size()) + if (e1->op == TOKsymoff && type->size() == e1->type->size() && + type->toBasetype()->ty != Tsarray) { e1->type = type; return e1; } - Type *tb = type->toBasetype(); + Type *tb = to->toBasetype(); if (tb->ty == Tbit) return new IntegerExp(loc, e1->toInteger() != 0, type); if (type->isintegral()) @@ -147,7 +143,7 @@ else if (tb->ty == Timaginary64) value = (double)value; #endif - return new ImaginaryExp(loc, value, type); + return new RealExp(loc, value, type); } if (tb->iscomplex()) { complex_t value = e1->toComplex(); @@ -174,7 +170,7 @@ if (tb->isscalar()) return new IntegerExp(loc, e1->toInteger(), type); if (tb->ty != Tvoid) - error("cannot cast %s to %s", e1->type->toChars(), type->toChars()); + error("cannot cast %s to %s", e1->type->toChars(), to->toChars()); return this; } @@ -193,7 +189,7 @@ } else if (type->isimaginary()) { - e = new ImaginaryExp(loc, e1->toImaginary() + e2->toImaginary(), type); + e = new RealExp(loc, e1->toImaginary() + e2->toImaginary(), type); } else if (type->iscomplex()) { @@ -230,7 +226,7 @@ } else if (type->isimaginary()) { - e = new ImaginaryExp(loc, e1->toImaginary() - e2->toImaginary(), type); + e = new RealExp(loc, e1->toImaginary() - e2->toImaginary(), type); } else if (type->iscomplex()) { @@ -257,22 +253,55 @@ e2 = e2->constFold(); if (type->isfloating()) { complex_t c; + d_float80 r; if (e1->type->isreal()) + { +#if __DMC__ c = e1->toReal() * e2->toComplex(); +#else + r = e1->toReal(); + c = e2->toComplex(); + c = complex_t(r * creall(c), r * cimagl(c)); +#endif + } else if (e1->type->isimaginary()) - c = e1->toImaginary() * e2->toComplex(); + { +#if __DMC__ + c = e1->toImaginary() * I * e2->toComplex(); +#else + r = e1->toImaginary(); + c = e2->toComplex(); + c = complex_t(-r * cimagl(c), r * creall(c)); +#endif + } else if (e2->type->isreal()) - c = e1->toComplex() * e2->toReal(); + { +#if __DMC__ + c = e2->toReal() * e1->toComplex(); +#else + r = e2->toReal(); + c = e1->toComplex(); + c = complex_t(r * creall(c), r * cimagl(c)); +#endif + } else if (e2->type->isimaginary()) - c = e1->toComplex() * e2->toImaginary(); + { +#if __DMC__ + c = e1->toComplex() * e2->toImaginary() * I; +#else + r = e2->toImaginary(); + c = e1->toComplex(); + c = complex_t(-r * cimagl(c), r * creall(c)); +#endif + } else c = e1->toComplex() * e2->toComplex(); if (type->isreal()) e = new RealExp(loc, creall(c), type); else if (type->isimaginary()) - e = new ImaginaryExp(loc, cimagl(c), type); + e = new RealExp(loc, cimagl(c), type); else if (type->iscomplex()) e = new ComplexExp(loc, c, type); else @@ -288,22 +317,57 @@ Expression *DivExp::constFold() { Expression *e; + //printf("DivExp::constFold(%s)\n", toChars()); e1 = e1->constFold(); e2 = e2->constFold(); if (type->isfloating()) { complex_t c; + d_float80 r; + //e1->type->print(); + //e2->type->print(); if (e2->type->isreal()) + { + if (e1->type->isreal()) + { + e = new RealExp(loc, e1->toReal() / e2->toReal(), type); + return e; + } +#if __DMC__ + //r = e2->toReal(); + //c = e1->toComplex(); + //printf("(%Lg + %Lgi) / %Lg\n", creall(c), cimagl(c), r); + c = e1->toComplex() / e2->toReal(); +#else + r = e2->toReal(); + c = e1->toComplex(); + c = complex_t(creall(c) / r, cimagl(c) / r); +#endif + } else if (e2->type->isimaginary()) - c = e1->toComplex() / e2->toImaginary(); + { +#if __DMC__ + //r = e2->toImaginary(); + //c = e1->toComplex(); + //printf("(%Lg + %Lgi) / %Lgi\n", creall(c), cimagl(c), r); + + c = e1->toComplex() / (e2->toImaginary() * I); +#else + r = e2->toImaginary(); + c = e1->toComplex(); + c = complex_t(cimagl(c) / r, -creall(c) / r); +#endif + } else + { c = e1->toComplex() / e2->toComplex(); + } if (type->isreal()) e = new RealExp(loc, creall(c), type); else if (type->isimaginary()) - e = new ImaginaryExp(loc, cimagl(c), type); + e = new RealExp(loc, cimagl(c), type); else if (type->iscomplex()) e = new ComplexExp(loc, c, type); else @@ -336,7 +400,6 @@ e2 = e2->constFold(); if (type->isfloating()) { -#if 1 complex_t c; if (e2->type->isreal()) @@ -363,29 +426,11 @@ if (type->isreal()) e = new RealExp(loc, creall(c), type); else if (type->isimaginary()) - e = new ImaginaryExp(loc, cimagl(c), type); + e = new RealExp(loc, cimagl(c), type); else if (type->iscomplex()) e = new ComplexExp(loc, c, type); else assert(0); -#else - if (type->isreal()) - { real_t c; - - c = fmodl(e1->toReal(), e2->toReal()); - e = new RealExp(loc, c, type); - } - else if (type->isimaginary()) - { real_t c; - - c = fmodl(e1->toImaginary(), e2->toImaginary()); - e = new RealExp(loc, c, type); - } - else - { - assert(0); - } -#endif } else { sinteger_t n1; diff -uNr dmd-0.139/dmd/src/dmd/expression.c dmd-0.140/dmd/src/dmd/expression.c --- dmd-0.139/dmd/src/dmd/expression.c 2005-10-24 11:29:10.000000000 +0200 +++ dmd-0.140/dmd/src/dmd/expression.c 2005-11-24 17:12:24.000000000 +0100 @@ -274,6 +274,10 @@ break; } default: + if (!arg) + { error(loc, "not enough arguments"); + return; + } break; } arg = arg->semantic(sc); @@ -507,6 +511,11 @@ buf->writestring(Token::toChars(op)); } +void Expression::toMangleBuffer(OutBuffer *buf) +{ + assert(0); +} + /******************************* * Give error if we're not an lvalue. * If we can, convert expression to be an lvalue. @@ -829,6 +838,14 @@ buf->printf("%lld", value); } +void IntegerExp::toMangleBuffer(OutBuffer *buf) +{ + if ((sinteger_t)value < 0) + buf->printf("N%lld", -value); + else + buf->printf("%lld", value); +} + /******************************** RealExp **************************/ RealExp::RealExp(Loc loc, real_t value, Type *type) @@ -841,36 +858,40 @@ char *RealExp::toChars() { - static char buffer[sizeof(value) * 3 + 8 + 1]; + static char buffer[sizeof(value) * 3 + 8 + 1 + 1]; - sprintf(buffer, "%Lg", value); + sprintf(buffer, type->isimaginary() ? "%Lgi" : "%Lg", value); assert(strlen(buffer) < sizeof(buffer)); return buffer; } integer_t RealExp::toInteger() { - return (sinteger_t) value; + return (sinteger_t) toReal(); } uinteger_t RealExp::toUInteger() { - return (uinteger_t) value; + return (uinteger_t) toReal(); } real_t RealExp::toReal() { - return value; + return type->isreal() ? value : 0; } real_t RealExp::toImaginary() { - return 0; + return type->isreal() ? 0 : value; } complex_t RealExp::toComplex() { - return value; +#ifdef __DMC__ + return toReal() + toImaginary() * I; +#else + return complex_t(toReal(), toImaginary()); +#endif } Expression *RealExp::semantic(Scope *sc) @@ -891,69 +912,17 @@ void RealExp::toCBuffer(OutBuffer *buf) { buf->printf("%Lg", value); + if (type->isimaginary()) + buf->writeByte('i'); } -/******************************** ImaginaryExp **************************/ - -ImaginaryExp::ImaginaryExp(Loc loc, real_t value, Type *type) - : Expression(loc, TOKimaginary80, sizeof(ImaginaryExp)) -{ - this->value = value; - this->type = type; -} - -char *ImaginaryExp::toChars() -{ - static char buffer[sizeof(value) * 3 + 8 + 1]; - - sprintf(buffer, "%Lgi", value); - assert(strlen(buffer) < sizeof(buffer)); - return buffer; -} - -integer_t ImaginaryExp::toInteger() -{ - return 0; -} - -real_t ImaginaryExp::toReal() -{ - return 0; -} - -real_t ImaginaryExp::toImaginary() -{ - return value; -} - -complex_t ImaginaryExp::toComplex() -{ -#ifdef __DMC__ - return value * I; -#else - return complex_t(0, value); -#endif -} - -Expression *ImaginaryExp::semantic(Scope *sc) -{ - if (!type) - type = Type::timaginary80; - else - type = type->semantic(loc, sc); - return this; -} - -int ImaginaryExp::isBool(int result) -{ - return result ? (value != 0) - : (value == 0); -} - -void ImaginaryExp::toCBuffer(OutBuffer *buf) +void RealExp::toMangleBuffer(OutBuffer *buf) { - buf->printf("%Lgi", value); + unsigned char *p = (unsigned char *)&value; + buf->writeByte('e'); + for (int i = 0; i < REALSIZE-REALPAD; i++) + buf->printf("%02x", p[i]); } @@ -978,17 +947,17 @@ integer_t ComplexExp::toInteger() { - return (sinteger_t) value; + return (sinteger_t) toReal(); } uinteger_t ComplexExp::toUInteger() { - return (uinteger_t) value; + return (uinteger_t) toReal(); } real_t ComplexExp::toReal() { - return (real_t) value; + return creall(value); } real_t ComplexExp::toImaginary() @@ -1021,6 +990,18 @@ buf->printf("(%Lg+%Lgi)", creall(value), cimagl(value)); } +void ComplexExp::toMangleBuffer(OutBuffer *buf) +{ + buf->writeByte('c'); + real_t r = toReal(); + for (int j = 0; j < 2; j++) + { + unsigned char *p = (unsigned char *)&r; + for (int i = 0; i < REALSIZE-REALPAD; i++) + buf->printf("%02x", p[i]); + r = toImaginary(); + } +} /******************************** IdentifierExp **************************/ @@ -1161,7 +1142,12 @@ { //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars()); if (!type) - type = v->type; + { type = v->type; + if (!v->type) + { error("forward reference of %s", v->toChars()); + type = Type::terror; + } + } if (v->isConst() && type->toBasetype()->ty != Tsarray) { if (v->init) @@ -1442,6 +1428,11 @@ buf->writestring("null"); } +void NullExp::toMangleBuffer(OutBuffer *buf) +{ + buf->writeByte('n'); +} + /******************************** StringExp **************************/ StringExp::StringExp(Loc loc, void *string, unsigned len) @@ -1664,6 +1655,58 @@ buf->writeByte(postfix); } +void StringExp::toMangleBuffer(OutBuffer *buf) +{ char m; + OutBuffer tmp; + char *p; + unsigned c; + unsigned u; + unsigned char *q; + unsigned qlen; + + /* Write string in UTF-8 format + */ + switch (sz) + { case 1: + m = 'a'; + q = (unsigned char *)string; + qlen = len; + break; + case 2: + m = 'w'; + for (u = 0; u < len; ) + { + p = utf_decodeWchar((unsigned short *)string, len, &u, &c); + if (p) + error(p); + else + tmp.writeUTF8(c); + } + q = tmp.data; + qlen = tmp.offset; + break; + case 4: + m = 'd'; + for (u = 0; u < len; u++) + { + c = ((unsigned *)string)[u]; + if (!utf_isValidDchar(c)) + error("invalid UCS-32 char \\U%08x", c); + else + tmp.writeUTF8(c); + } + q = tmp.data; + qlen = tmp.offset; + break; + default: + assert(0); + } + buf->writeByte(m); + buf->printf("%d_", qlen); + for (size_t i = 0; i < qlen; i++) + buf->printf("%02x", q[i]); +} + /************************ TypeDotIdExp ************************************/ /* Things like: @@ -3008,7 +3051,7 @@ void DotIdExp::toCBuffer(OutBuffer *buf) { - //printf("DotIdExp::toCbuffer()\n"); + //printf("DotIdExp::toCBuffer()\n"); e1->toCBuffer(buf); buf->writeByte('.'); buf->writestring(ident->toChars()); @@ -5458,6 +5501,7 @@ case Timaginary80: type = Type::tfloat80; break; default: assert(0); } + // iy * iv = -yv e1->type = type; e2->type = type; diff -uNr dmd-0.139/dmd/src/dmd/expression.h dmd-0.140/dmd/src/dmd/expression.h --- dmd-0.139/dmd/src/dmd/expression.h 2005-10-30 15:00:00.000000000 +0100 +++ dmd-0.140/dmd/src/dmd/expression.h 2005-11-20 23:15:04.000000000 +0100 @@ -73,6 +73,7 @@ virtual real_t toImaginary(); virtual complex_t toComplex(); virtual void toCBuffer(OutBuffer *buf); + virtual void toMangleBuffer(OutBuffer *buf); virtual Expression *toLvalue(Expression *e); virtual Expression *modifiableLvalue(Scope *sc, Expression *e); Expression *implicitCastTo(Type *t); @@ -130,6 +131,7 @@ int isBool(int result); int implicitConvTo(Type *t); void toCBuffer(OutBuffer *buf); + void toMangleBuffer(OutBuffer *buf); Expression *toLvalue(Expression *e); elem *toElem(IRState *irs); dt_t **toDt(dt_t **pdt); @@ -150,24 +152,7 @@ int isConst(); int isBool(int result); void toCBuffer(OutBuffer *buf); - elem *toElem(IRState *irs); - dt_t **toDt(dt_t **pdt); -}; - -struct ImaginaryExp : Expression -{ - real_t value; - - ImaginaryExp(Loc loc, real_t value, Type *type); - Expression *semantic(Scope *sc); - char *toChars(); - integer_t toInteger(); - real_t toReal(); - real_t toImaginary(); - complex_t toComplex(); - int isConst(); - int isBool(int result); - void toCBuffer(OutBuffer *buf); + void toMangleBuffer(OutBuffer *buf); elem *toElem(IRState *irs); dt_t **toDt(dt_t **pdt); }; @@ -187,6 +172,7 @@ int isConst(); int isBool(int result); void toCBuffer(OutBuffer *buf); + void toMangleBuffer(OutBuffer *buf); elem *toElem(IRState *irs); dt_t **toDt(dt_t **pdt); }; @@ -256,6 +242,7 @@ Expression *semantic(Scope *sc); int isBool(int result); void toCBuffer(OutBuffer *buf); + void toMangleBuffer(OutBuffer *buf); int implicitConvTo(Type *t); Expression *castTo(Type *t); elem *toElem(IRState *irs); @@ -280,6 +267,7 @@ int compare(Object *obj); int isBool(int result); void toCBuffer(OutBuffer *buf); + void toMangleBuffer(OutBuffer *buf); elem *toElem(IRState *irs); dt_t **toDt(dt_t **pdt); }; diff -uNr dmd-0.139/dmd/src/dmd/mars.c dmd-0.140/dmd/src/dmd/mars.c --- dmd-0.139/dmd/src/dmd/mars.c 2005-11-06 23:34:18.000000000 +0100 +++ dmd-0.140/dmd/src/dmd/mars.c 2005-11-13 00:43:02.000000000 +0100 @@ -51,7 +51,7 @@ copyright = "Copyright (c) 1999-2005 by Digital Mars"; written = "written by Walter Bright"; - version = "v0.139"; + version = "v0.140"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); @@ -383,7 +383,9 @@ else if (strcmp(p + 1, "-f") == 0) global.params.debugf = 1; else if (strcmp(p + 1, "-help") == 0) - usage(); + { usage(); + exit(EXIT_SUCCESS); + } else if (strcmp(p + 1, "-r") == 0) global.params.debugr = 1; else if (strcmp(p + 1, "-x") == 0) diff -uNr dmd-0.139/dmd/src/dmd/mtype.c dmd-0.140/dmd/src/dmd/mtype.c --- dmd-0.139/dmd/src/dmd/mtype.c 2005-11-06 23:36:20.000000000 +0100 +++ dmd-0.140/dmd/src/dmd/mtype.c 2005-11-23 14:47:42.000000000 +0100 @@ -54,8 +54,10 @@ int PTRSIZE = 4; #if TARGET_LINUX int REALSIZE = 12; +int REALPAD = 2; #else int REALSIZE = 10; +int REALPAD = 0; #endif int Tsize_t = Tuns32; int Tptrdiff_t = Tint32; @@ -197,8 +199,10 @@ PTRSIZE = 4; #if TARGET_LINUX REALSIZE = 12; + REALPAD = 2; #else REALSIZE = 10; + REALPAD = 0; #endif Tsize_t = Tuns32; Tptrdiff_t = Tint32; @@ -1081,10 +1085,8 @@ return e; Lfvalue: - if (isreal()) + if (isreal() || isimaginary()) e = new RealExp(0, fvalue, this); - else if (isimaginary()) - e = new ImaginaryExp(0, fvalue, this); else { complex_t cvalue; @@ -1598,7 +1600,8 @@ int TypeSArray::isString() { - return next->ty == Tascii || next->ty == Twchar || next->ty == Tdchar; + TY nty = next->toBasetype()->ty; + return nty == Tchar || nty == Twchar || nty == Tdchar; } unsigned TypeSArray::memalign(unsigned salign) @@ -1738,7 +1741,8 @@ int TypeDArray::isString() { - return next->ty == Tascii || next->ty == Twchar || next->ty == Tdchar; + TY nty = next->toBasetype()->ty; + return nty == Tchar || nty == Twchar || nty == Tdchar; } int TypeDArray::implicitConvTo(Type *to) @@ -2242,7 +2246,7 @@ case LINKc: mc = 'U'; break; case LINKwindows: mc = 'W'; break; case LINKpascal: mc = 'V'; break; - case LINKcpp: mc = 'T'; break; + case LINKcpp: mc = 'R'; break; default: assert(0); } diff -uNr dmd-0.139/dmd/src/dmd/mtype.h dmd-0.140/dmd/src/dmd/mtype.h --- dmd-0.139/dmd/src/dmd/mtype.h 2005-10-25 14:50:42.000000000 +0200 +++ dmd-0.140/dmd/src/dmd/mtype.h 2005-11-09 10:25:10.000000000 +0100 @@ -604,6 +604,7 @@ extern int PTRSIZE; extern int REALSIZE; +extern int REALPAD; extern int Tsize_t; extern int Tptrdiff_t; diff -uNr dmd-0.139/dmd/src/dmd/parse.c dmd-0.140/dmd/src/dmd/parse.c --- dmd-0.139/dmd/src/dmd/parse.c 2005-10-25 00:09:54.000000000 +0200 +++ dmd-0.140/dmd/src/dmd/parse.c 2005-11-10 10:59:38.000000000 +0100 @@ -3694,17 +3694,17 @@ break; case TOKimaginary32v: - e = new ImaginaryExp(loc, token.float80value, Type::timaginary32); + e = new RealExp(loc, token.float80value, Type::timaginary32); nextToken(); break; case TOKimaginary64v: - e = new ImaginaryExp(loc, token.float80value, Type::timaginary64); + e = new RealExp(loc, token.float80value, Type::timaginary64); nextToken(); break; case TOKimaginary80v: - e = new ImaginaryExp(loc, token.float80value, Type::timaginary80); + e = new RealExp(loc, token.float80value, Type::timaginary80); nextToken(); break; diff -uNr dmd-0.139/dmd/src/dmd/template.c dmd-0.140/dmd/src/dmd/template.c --- dmd-0.139/dmd/src/dmd/template.c 2005-10-24 11:28:24.000000000 +0200 +++ dmd-0.140/dmd/src/dmd/template.c 2005-11-20 23:24:52.000000000 +0100 @@ -1071,8 +1071,9 @@ sparam->semantic(sc); valType = valType->semantic(loc, sc); - if (!valType->isintegral() && valType->ty != Tident) - error(loc, "integral type expected for value-parameter, not %s", valType->toChars()); + if (!(valType->isintegral() || valType->isfloating() || valType->isString()) && + valType->ty != Tident) + error(loc, "arithmetic/string type expected for value-parameter, not %s", valType->toChars()); if (specValue) { Expression *e = specValue; @@ -1080,7 +1081,8 @@ e = e->semantic(sc); e = e->implicitCastTo(valType); e = e->constFold(); - if (e->op == TOKint64) + if (e->op == TOKint64 || e->op == TOKfloat64 || + e->op == TOKcomplex80 || e->op == TOKnull || e->op == TOKstring) specValue = e; //e->toInteger(); } @@ -1200,7 +1202,7 @@ { // Create a dummy value if (!edummy) - edummy = new IntegerExp(0); + edummy = valType->defaultInit(); e = edummy; } return (void *)e; @@ -1723,23 +1725,27 @@ char *id; //printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars()); - buf.writestring(tempdecl->ident->toChars()); - buf.writeByte('_'); + id = tempdecl->ident->toChars(); + buf.printf("__T%d%s", strlen(id), id); for (int i = 0; i < tiargs->dim; i++) { Object *o = (Object *)tiargs->data[i]; - //Object *o = (Object *)tdtypes.data[i]; Type *ta = isType(o); Expression *ea = isExpression(o); Dsymbol *sa = isDsymbol(o); if (ta) { + buf.writeByte('T'); if (ta->deco) buf.writestring(ta->deco); else assert(global.errors); } else if (ea) - { + { sinteger_t v; + real_t r; + int i; + unsigned char *p; + if (ea->op == TOKvar) { sa = ((VarExp *)ea)->var; @@ -1752,12 +1758,14 @@ ea = NULL; goto Lsa; } - buf.writeByte('_'); - buf.printf("%u", ea->toInteger()); + buf.writeByte('V'); + buf.writestring(ea->type->deco); + ea->toMangleBuffer(&buf); } else if (sa) { Lsa: + buf.writeByte('S'); Declaration *d = sa->isDeclaration(); if (d && !d->isDataseg() && !d->isFuncDeclaration() && !isTemplateMixin()) { @@ -1768,12 +1776,13 @@ else { char *p = sa->mangle(); - buf.printf("__%u_%s", strlen(p) + 1, p); + buf.printf("%d%s", strlen(p), p); } } else assert(0); } + buf.writeByte('Z'); id = buf.toChars(); buf.data = NULL; return new Identifier(id, TOKidentifier); diff -uNr dmd-0.139/dmd/src/dmd/todt.c dmd-0.140/dmd/src/dmd/todt.c --- dmd-0.139/dmd/src/dmd/todt.c 2005-11-06 23:36:20.000000000 +0100 +++ dmd-0.140/dmd/src/dmd/todt.c 2005-11-10 11:31:50.000000000 +0100 @@ -419,21 +419,22 @@ switch (type->toBasetype()->ty) { case Tfloat32: + case Timaginary32: fvalue = value; pdt = dtnbytes(pdt,4,(char *)&fvalue); break; case Tfloat64: + case Timaginary64: dvalue = value; pdt = dtnbytes(pdt,8,(char *)&dvalue); break; case Tfloat80: + case Timaginary80: evalue = value; - pdt = dtnbytes(pdt,10,(char *)&evalue); -#if TARGET_LINUX - pdt = dtnbytes(pdt,2,zeropad); -#endif + pdt = dtnbytes(pdt,REALSIZE - REALPAD,(char *)&evalue); + pdt = dtnbytes(pdt,REALPAD,zeropad); break; default: @@ -445,39 +446,6 @@ return pdt; } -dt_t **ImaginaryExp::toDt(dt_t **pdt) -{ - d_float32 fvalue; - d_float64 dvalue; - d_float80 evalue; - - switch (type->toBasetype()->ty) - { - case Timaginary32: - fvalue = value; - pdt = dtnbytes(pdt,4,(char *)&fvalue); - break; - - case Timaginary64: - dvalue = value; - pdt = dtnbytes(pdt,8,(char *)&dvalue); - break; - - case Timaginary80: - evalue = value; - pdt = dtnbytes(pdt,10,(char *)&evalue); -#if TARGET_LINUX - pdt = dtnbytes(pdt,2,zeropad); -#endif - break; - - default: - assert(0); - break; - } - return pdt; -} - dt_t **ComplexExp::toDt(dt_t **pdt) { d_float32 fvalue; @@ -502,15 +470,11 @@ case Tcomplex80: evalue = creall(value); - pdt = dtnbytes(pdt,10,(char *)&evalue); -#if TARGET_LINUX - pdt = dtnbytes(pdt,2,zeropad); -#endif + pdt = dtnbytes(pdt,REALSIZE - REALPAD,(char *)&evalue); + pdt = dtnbytes(pdt,REALPAD,zeropad); evalue = cimagl(value); - pdt = dtnbytes(pdt,10,(char *)&evalue); -#if TARGET_LINUX - pdt = dtnbytes(pdt,2,zeropad); -#endif + pdt = dtnbytes(pdt,REALSIZE,(char *)&evalue); + pdt = dtnbytes(pdt,REALSIZE - REALPAD,zeropad); break; default: diff -uNr dmd-0.139/dmd/src/phobos/linux.mak dmd-0.140/dmd/src/phobos/linux.mak --- dmd-0.139/dmd/src/phobos/linux.mak 2005-11-06 11:16:16.000000000 +0100 +++ dmd-0.140/dmd/src/phobos/linux.mak 2005-11-24 17:12:54.000000000 +0100 @@ -57,6 +57,7 @@ process.o syserror.o \ socket.o socketstream.o stdarg.o stdio.o format.o \ perf.o openrj.o uni.o trace.o boxer.o \ + demangle.o \ ti_wchar.o ti_uint.o ti_short.o ti_ushort.o \ ti_byte.o ti_ubyte.o ti_long.o ti_ulong.o ti_ptr.o \ ti_float.o ti_double.o ti_real.o ti_delegate.o \ @@ -99,7 +100,7 @@ std/regexp.d std/random.d std/stream.d std/process.d std/recls.d \ std/socket.d std/socketstream.d std/loader.d std/stdarg.d \ std/stdio.d std/format.d std/perf.d std/openrj.d std/uni.d \ - std/boxer.d std/cstream.d + std/boxer.d std/cstream.d std/demangle.d SRC_STD_C= std/c/process.d std/c/stdlib.d std/c/time.d std/c/stdio.d \ std/c/math.d std/c/stdarg.d std/c/stddef.d @@ -139,7 +140,7 @@ internal/object.d internal/trace.d internal/qsort2.d SRC_STD_WIN= std/windows/registry.d \ - std/windows/iunknown.d + std/windows/iunknown.d std/windows/charset.d SRC_STD_C_WIN= std/c/windows/windows.d std/c/windows/com.d \ std/c/windows/winsock.d @@ -493,6 +494,9 @@ dateparse.o : std/dateparse.d std/date.d $(DMD) -c $(DFLAGS) std/dateparse.d +demangle.o : std/demangle.d + $(DMD) -c $(DFLAGS) std/demangle.d + file.o : std/file.d $(DMD) -c $(DFLAGS) std/file.d diff -uNr dmd-0.139/dmd/src/phobos/std/date.d dmd-0.140/dmd/src/phobos/std/date.d --- dmd-0.139/dmd/src/phobos/std/date.d 2005-11-06 11:16:18.000000000 +0100 +++ dmd-0.140/dmd/src/phobos/std/date.d 2005-11-24 17:12:54.000000000 +0100 @@ -147,36 +147,37 @@ return d / divisor; } -d_time dmod(d_time n, d_time d) +int dmod(d_time n, d_time d) { d_time r; r = n % d; if (r < 0) r += d; - return r; + assert(cast(int)r == r); + return cast(int)r; } -d_time HourFromTime(d_time t) +int HourFromTime(d_time t) { return dmod(floor(t, msPerHour), HoursPerDay); } -d_time MinFromTime(d_time t) +int MinFromTime(d_time t) { return dmod(floor(t, msPerMinute), MinutesPerHour); } -d_time SecFromTime(d_time t) +int SecFromTime(d_time t) { return dmod(floor(t, TicksPerSecond), 60); } -d_time msFromTime(d_time t) +int msFromTime(d_time t) { return dmod(t / (TicksPerSecond / 1000), 1000); } -d_time TimeWithinDay(d_time t) +int TimeWithinDay(d_time t) { return dmod(t, msPerDay); } @@ -359,19 +360,8 @@ return t - LocalTZA - DaylightSavingTA(t - LocalTZA); } -d_time MakeTime(d_time hour, d_time min, d_time sec, d_time ms) +d_time MakeTime(int hour, int min, int sec, int ms) { - if (hour == d_time_nan || - min == d_time_nan || - sec == d_time_nan || - ms == d_time_nan) - return d_time_nan; - - hour = toInteger(hour); - min = toInteger(min); - sec = toInteger(sec); - ms = toInteger(ms); - return hour * TicksPerHour + min * TicksPerMinute + sec * TicksPerSecond + @@ -379,25 +369,14 @@ } -d_time MakeDay(d_time year, d_time month, d_time date) +d_time MakeDay(int year, int month, int date) { d_time t; int y; int m; int leap; - if (year == d_time_nan || - month == d_time_nan || - date == d_time_nan) - { - return d_time_nan; - } - - year = toInteger(year); - month = toInteger(month); - date = toInteger(date); - y = cast(int)(year + floor(month, 12)); - m = cast(int)dmod(month, 12); + m = dmod(month, 12); leap = LeapYear(y); t = TimeFromYear(y) + cast(d_time)mdays[m] * msPerDay; @@ -485,7 +464,7 @@ &daystr[WeekDay(t) * 3], &monstr[MonthFromTime(t) * 3], DateFromTime(t), - cast(int)HourFromTime(t), cast(int)MinFromTime(t), cast(int)SecFromTime(t), + HourFromTime(t), MinFromTime(t), SecFromTime(t), sign, hr, mn, cast(long)YearFromTime(t)); @@ -515,7 +494,7 @@ &daystr[WeekDay(t) * 3], DateFromTime(t), &monstr[MonthFromTime(t) * 3], YearFromTime(t), - cast(int)HourFromTime(t), cast(int)MinFromTime(t), cast(int)SecFromTime(t)); + HourFromTime(t), MinFromTime(t), SecFromTime(t)); // Ensure no buggy buffer overflows assert(len < buffer.length); @@ -598,7 +577,7 @@ //printf("hr = %d, offset = %g, LocalTZA = %g, dst = %g, + = %g\n", hr, offset, LocalTZA, dst, LocalTZA + dst); len = sprintf(buffer, "%02d:%02d:%02d GMT%c%02d%02d", - cast(int)HourFromTime(t), cast(int)MinFromTime(t), cast(int)SecFromTime(t), + HourFromTime(t), MinFromTime(t), SecFromTime(t), sign, hr, mn); // Ensure no buggy buffer overflows diff -uNr dmd-0.139/dmd/src/phobos/std/demangle.d dmd-0.140/dmd/src/phobos/std/demangle.d --- dmd-0.139/dmd/src/phobos/std/demangle.d 1970-01-01 01:00:00.000000000 +0100 +++ dmd-0.140/dmd/src/phobos/std/demangle.d 2005-11-24 17:12:54.000000000 +0100 @@ -0,0 +1,469 @@ +/**** + * Demangle D mangled names. + */ + +module std.demangle; + +//debug=demangle; // uncomment to turn on debugging printf's + +private import std.ctype; +private import std.string; +private import std.utf; + +private import std.stdio; + +private class MangleException : Exception +{ + this() + { + super("MangleException"); + } +} + +/***************************** + * Demangle D mangled names. + * + * If it is not a D mangled name, it returns its argument name. + * Example: + * This program reads standard in and writes it to standard out, + * pretty-printing any found D mangled names. +------------------- +import std.stdio; +import std.ctype; +import std.demangle; + +int main() +{ char[] buffer; + bit inword; + int c; + + while ((c = fgetc(stdin)) != EOF) + { + if (inword) + { + if (c == '_' || isalnum(c)) + buffer ~= cast(char) c; + else + { + inword = false; + writef(demangle(buffer), cast(char) c); + } + } + else + { if (c == '_' || isalpha(c)) + { inword = true; + buffer.length = 0; + buffer ~= cast(char) c; + } + else + writef(cast(char) c); + } + } + if (inword) + writef(demangle(buffer)); + return 0; +} +------------------- + */ + +char[] demangle(char[] name) +{ + size_t ni = 2; + char[] delegate() fparseTemplateInstanceName; + + static void error() + { + //writefln("error()"); + throw new MangleException(); + } + + static ubyte ascii2hex(char c) + { + if (!isxdigit(c)) + error(); + return (c >= 'a') ? c - 'a' + 10 : + (c >= 'A') ? c - 'A' + 10 : + c - '0'; + } + + size_t parseNumber() + { + //writefln("parseNumber() %d", ni); + size_t result; + + while (ni < name.length && isdigit(name[ni])) + { int i = name[ni] - '0'; + if (result > (size_t.max - i) / 10) + error(); + result = result * 10 + i; + ni++; + } + return result; + } + + char[] parseSymbolName() + { + //writefln("parseSymbolName() %d", ni); + size_t i = parseNumber(); + if (ni + i > name.length) + error(); + char[] result; + if (i >= 5 && + name[ni] == '_' && + name[ni + 1] == '_' && + name[ni + 2] == 'T') + { + size_t nisave = ni; + bit err; + ni += 3; + try + { + result = fparseTemplateInstanceName(); + if (ni != nisave + i) + err = true; + } + catch (MangleException me) + { + err = true; + } + ni = nisave; + if (err) + goto L1; + goto L2; + } + L1: + result = name[ni .. ni + i]; + L2: + ni += i; + return result; + } + + char[] parseQualifiedName() + { + //writefln("parseQualifiedName() %d", ni); + char[] result; + + while (ni < name.length && isdigit(name[ni])) + { + if (result.length) + result ~= "."; + result ~= parseSymbolName(); + } + return result; + } + + char[] parseType(char[] identifier = null) + { + //writefln("parseType() %d", ni); + int isdelegate = 0; + Lagain: + if (ni >= name.length) + error(); + char[] p; + switch (name[ni++]) + { + case 'v': p = "void"; goto L1; + case 'b': p = "bit"; goto L1; + case 'g': p = "byte"; goto L1; + case 'h': p = "ubyte"; goto L1; + case 's': p = "short"; goto L1; + case 't': p = "ushort"; goto L1; + case 'i': p = "int"; goto L1; + case 'k': p = "uint"; goto L1; + case 'l': p = "long"; goto L1; + case 'm': p = "ulong"; goto L1; + case 'f': p = "float"; goto L1; + case 'd': p = "double"; goto L1; + case 'e': p = "real"; goto L1; + case 'o': p = "ifloat"; goto L1; + case 'p': p = "idouble"; goto L1; + case 'j': p = "ireal"; goto L1; + case 'q': p = "cfloat"; goto L1; + case 'r': p = "cdouble"; goto L1; + case 'c': p = "creal"; goto L1; + case 'a': p = "char"; goto L1; + case 'u': p = "wchar"; goto L1; + case 'w': p = "dchar"; goto L1; + + case 'A': // dynamic array + p = parseType() ~ "[]"; + goto L1; + + case 'P': // pointer + p = parseType() ~ "*"; + goto L1; + + case 'G': // static array + { size_t ns = ni; + parseNumber(); + size_t ne = ni; + p = parseType() ~ "[" ~ name[ns .. ne] ~ "]"; + goto L1; + } + + case 'H': // associative array + p = parseType(); + p = parseType() ~ "[" ~ p ~ "]"; + goto L1; + + case 'D': // delegate + isdelegate = 1; + goto Lagain; + + case 'F': // D function + case 'U': // C function + case 'W': // Windows function + case 'V': // Pascal function + case 'R': // C++ function + { char mc = name[ni - 1]; + char[] args; + + while (1) + { + if (ni >= name.length) + error(); + char c = name[ni]; + if (c == 'Z') + break; + if (args.length) + args ~= ", "; + switch (c) + { + case 'J': + args ~= "out "; + ni++; + goto default; + + case 'K': + args ~= "inout "; + ni++; + goto default; + + default: + args ~= parseType(); + continue; + + case 'Y': + args ~= "..."; + break; + } + break; + } + ni++; + if (!isdelegate && identifier.length) + { + switch (mc) + { + case 'F': p = null; break; // D function + case 'U': p = "extern (C) "; break; // C function + case 'W': p = "extern (Windows) "; break; // Windows function + case 'V': p = "extern (Pascal) "; break; // Pascal function + } + p ~= parseType() ~ " " ~ identifier ~ "(" ~ args ~ ")"; + return p; + } + p = parseType() ~ + (isdelegate ? " delegate(" : " function(") ~ + args ~ + ")"; + isdelegate = 0; + goto L1; + } + + case 'C': p = "class "; goto L2; + case 'S': p = "struct "; goto L2; + case 'E': p = "enum "; goto L2; + case 'T': p = "typedef "; goto L2; + + L2: p ~= parseQualifiedName(); + goto L1; + + L1: + if (isdelegate) + error(); // 'D' must be followed by function + if (identifier.length) + p ~= " " ~ identifier; + return p; + + default: + size_t i = ni - 1; + ni = name.length; + p = name[i .. length]; + goto L1; + } + } + + char[] parseTemplateInstanceName() + { + char[] result = parseSymbolName() ~ "!("; + int nargs; + + while (1) + { size_t i; + + if (ni >= name.length) + error(); + if (nargs && name[ni] != 'Z') + result ~= ", "; + nargs++; + switch (name[ni++]) + { + case 'T': + result ~= parseType(); + continue; + + case 'V': + + void getReal() + { real r; + ubyte *p = cast(ubyte *)&r; + + if (ni + 10 * 2 > name.length) + error(); + for (i = 0; i < 10; i++) + { ubyte b; + + b = (ascii2hex(name[ni + i * 2]) << 4) + + ascii2hex(name[ni + i * 2 + 1]); + p[i] = b; + } + result ~= format(r); + ni += 10 * 2; + } + + result ~= parseType() ~ " "; + if (ni >= name.length) + error(); + switch (name[ni++]) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + i = ni - 1; + while (ni < name.length && isdigit(name[ni])) + ni++; + result ~= name[i .. ni]; + break; + + case 'N': + i = ni; + while (ni < name.length && isdigit(name[ni])) + ni++; + if (i == ni) + error(); + result ~= "-" ~ name[i .. ni]; + break; + + case 'n': + result ~= "null"; + break; + + case 'e': + getReal(); + break; + + case 'c': + getReal(); + result ~= '+'; + getReal(); + result ~= 'i'; + break; + + case 'a': + case 'w': + case 'd': + { char m = name[ni - 1]; + if (m == 'a') + m = 'c'; + size_t n = parseNumber(); + if (ni >= name.length || name[ni++] != '_' || + ni + n * 2 > name.length) + error(); + result ~= '"'; + for (i = 0; i < n; i++) + { char c; + + c = (ascii2hex(name[ni + i * 2]) << 4) + + ascii2hex(name[ni + i * 2 + 1]); + result ~= c; + } + ni += n * 2; + result ~= '"'; + result ~= m; + break; + } + + default: + error(); + break; + } + continue; + + case 'S': + result ~= parseSymbolName(); + continue; + + case 'Z': + break; + + default: + error(); + } + break; + } + result ~= ")"; + return result; + } + + if (name.length < 3 || + name[0] != '_' || + name[1] != 'D' || + !isdigit(name[2])) + { + goto Lnot; + } + + fparseTemplateInstanceName = &parseTemplateInstanceName; + + try + { + char[] result = parseQualifiedName(); + result = parseType(result); + if (ni != name.length) + goto Lnot; + return result; + } + catch (MangleException e) + { + } + +Lnot: + // Not a recognized D mangled name; so return original + return name; +} + + +unittest +{ + debug(demangle) printf("demangle.demangle.unittest\n"); + + static char[][2][] table = + [ + [ "printf", "printf" ], + [ "_foo", "_foo" ], + [ "_D88", "_D88" ], + [ "_D4test3fooAa", "char[] test.foo"], + [ "_D8demangle8demangleFAaZAa", "char[] demangle.demangle(char[])" ], + [ "_D6object6Object8opEqualsFC6ObjectZi", "int object.Object.opEquals(class Object)" ], + [ "_D4test2dgDFiYd", "double delegate(int, ...) test.dg" ], + [ "_D4test58__T9factorialVde67666666666666860140VG5aa5_68656c6c6fVPvnZ9factorialf", "float test.factorial!(double 4.2, char[5] \"hello\"c, void* null).factorial" ], + [ "_D4test101__T9factorialVde67666666666666860140Vrc9a999999999999d9014000000000000000c00040VG5aa5_68656c6c6fVPvnZ9factorialf", "float test.factorial!(double 4.2, cdouble 6.8+3i, char[5] \"hello\"c, void* null).factorial" ], + [ "_D4test34__T3barVG3uw3_616263VG3wd3_646566Z1xi", "int test.bar!(wchar[3] \"abc\"w, dchar[3] \"def\"d).x" ], + ]; + + foreach (char[][2] name; table) + { + char[] r = demangle(name[0]); + //writefln("[ \"%s\", \"%s\" ],", name[0], r); + assert(r == name[1]); + } +} diff -uNr dmd-0.139/dmd/src/phobos/std/file.d dmd-0.140/dmd/src/phobos/std/file.d --- dmd-0.139/dmd/src/phobos/std/file.d 2005-11-06 11:16:18.000000000 +0100 +++ dmd-0.140/dmd/src/phobos/std/file.d 2005-11-24 17:12:54.000000000 +0100 @@ -40,6 +40,7 @@ private import std.c.windows.windows; private import std.utf; private import std.windows.syserror; +private import std.windows.charset; int useWfuncs = 1; @@ -488,9 +489,10 @@ h = FindFirstFileA(toMBSz(c), &fileinfo); if (h != INVALID_HANDLE_VALUE) // should we throw exception if invalid? { + wchar[] wbuf; do { int clength; - wchar[] wbuf; + int wlength; int n; // Skip "." and ".." @@ -501,11 +503,13 @@ clength = std.string.strlen(fileinfo.cFileName); // Convert cFileName[] to unicode - wbuf.length = MultiByteToWideChar(0,0,fileinfo.cFileName,clength,null,0); - n = MultiByteToWideChar(0,0,fileinfo.cFileName,clength,cast(wchar*)wbuf,wbuf.length); - assert(n == wbuf.length); + wlength = MultiByteToWideChar(0,0,fileinfo.cFileName,clength,null,0); + if (wlength > wbuf.length) + wbuf.length = wlength; + n = MultiByteToWideChar(0,0,fileinfo.cFileName,clength,cast(wchar*)wbuf,wlength); + assert(n == wlength); // toUTF8() returns a new buffer - if (!callback(std.utf.toUTF8(wbuf))) + if (!callback(std.utf.toUTF8(wbuf[0 .. wlength]))) break; } while (FindNextFileA(h,&fileinfo) != FALSE); FindClose(h); @@ -518,24 +522,12 @@ * to wchar, then convert to multibyte using the current code * page. * (Thanks to yaneurao for this) + * Deprecated: use std.windows.charset.toMBSz instead. */ char* toMBSz(char[] s) { - // Only need to do this if any chars have the high bit set - foreach (char c; s) - { - if (c >= 0x80) - { char[] result; - int i; - wchar* ws = std.utf.toUTF16z(s); - result.length = WideCharToMultiByte(0, 0, ws, -1, null, 0, null, null); - i = WideCharToMultiByte(0, 0, ws, -1, result, result.length, null, null); - assert(i == result.length); - return result; - } - } - return std.string.toStringz(s); + return std.windows.charset.toMBSz(s); } diff -uNr dmd-0.139/dmd/src/phobos/std/format.d dmd-0.140/dmd/src/phobos/std/format.d --- dmd-0.139/dmd/src/phobos/std/format.d 2005-11-06 11:16:18.000000000 +0100 +++ dmd-0.140/dmd/src/phobos/std/format.d 2005-11-24 17:12:54.000000000 +0100 @@ -640,7 +640,7 @@ } else { if (!isValidDchar(vdchar)) - throw new UtfError("invalid dchar in format", 0); + throw new UtfException("invalid dchar in format", 0); char[4] vbuf; putstr(toUTF8(vbuf, vdchar)); } diff -uNr dmd-0.139/dmd/src/phobos/std/string.d dmd-0.140/dmd/src/phobos/std/string.d --- dmd-0.139/dmd/src/phobos/std/string.d 2005-11-06 11:16:18.000000000 +0100 +++ dmd-0.140/dmd/src/phobos/std/string.d 2005-11-24 17:12:54.000000000 +0100 @@ -81,13 +81,17 @@ "abcdefghijklmnopqrstuvwxyz"; /// A..Za..z const char[6] whitespace = " \t\v\r\n\f"; /// ASCII whitespace +const dchar LS = '\u2028'; /// UTF line separator +const dchar PS = '\u2029'; /// UTF paragraph separator + /********************************** * Returns !=0 if c is whitespace */ int iswhite(dchar c) { - return find(whitespace, c) != -1; + return (c <= 0x7F) ? find(whitespace, c) != -1 + : (c == PS || c == LS); } /********************************* @@ -1604,7 +1608,7 @@ { len--; if (len == 0) - throw new std.utf.UtfError("invalid UTF sequence", 0); + throw new std.utf.UtfException("invalid UTF sequence", 0); } return s[0 .. len - 1]; @@ -1882,44 +1886,58 @@ * tabsize is the distance between tab stops. */ -char[] expandtabs(char[] s, int tabsize) +char[] expandtabs(char[] string, int tabsize = 8) { - char[] r; - int i; - int istart; - int col; - static char[8] spaces = " "; + bool changes = false; + char[] result = string; + int column; + int nspaces; - col = 0; - for (i = 0; i < s.length; i++) + foreach (size_t i, dchar c; string) { - char c; - - c = s[i]; - if (c == '\t') - { int tabstop; + switch (c) + { + case '\t': + nspaces = tabsize - (column % tabsize); + if (!changes) + { + changes = true; + result = null; + result.length = string.length + nspaces - 1; + result.length = i + nspaces; + result[0 .. i] = string[0 .. i]; + result[i .. i + nspaces] = ' '; + } + else + { int j = result.length; + result.length = j + nspaces; + result[j .. j + nspaces] = ' '; + } + column += nspaces; + break; - r ~= s[istart .. i]; - istart = i + 1; + case '\r': + case '\n': + case PS: + case LS: + column = 0; + goto L1; - tabstop = col + tabsize; - tabstop -= tabstop % tabsize; - while (col < tabstop) - { - int n = tabstop - col; - if (n > spaces.length) - n = spaces.length; - r ~= spaces[0 .. n]; - col += n; - } - } - else - { - col++; + default: + column++; + L1: + if (changes) + { + if (c <= 0x7F) + result ~= c; + else + std.utf.encode(result, c); + } + break; } } - r ~= s[istart .. i]; - return r; + + return result; } unittest @@ -1933,9 +1951,168 @@ r = expandtabs(s, 8); i = cmp(r, "This is a fofof of list"); assert(i == 0); + + r = expandtabs(null); + assert(r == null); + r = expandtabs(""); + assert(r.length == 0); + r = expandtabs("a"); + assert(r == "a"); + r = expandtabs("\t"); + assert(r == " "); + r = expandtabs( " ab\tasdf "); + //writefln("r = '%s'", r); + assert(r == " ab asdf "); + // TODO: need UTF test case } +/******************************************* + * Replace spaces in string with the optimal number of tabs. + * Trailing spaces or tabs in a line are removed. + * Params: + * string = String to convert. + * tabsize = Tab columns are tabsize spaces apart. tabsize defaults to 8. + */ + +char[] entab(char[] string, int tabsize = 8) +{ + bool changes = false; + char[] result = string; + + int nspaces = 0; + int nwhite = 0; + int column = 0; // column number + + foreach (size_t i, dchar c; string) + { + + void change() + { + changes = true; + result = null; + result.length = string.length; + result.length = i; + result[0 .. i] = string[0 .. i]; + } + + switch (c) + { + case '\t': + nwhite++; + if (nspaces) + { + if (!changes) + change(); + + int j = result.length - nspaces; + int ntabs = (((column - nspaces) % tabsize) + nspaces) / tabsize; + result.length = j + ntabs; + result[j .. j + ntabs] = '\t'; + nwhite += ntabs - nspaces; + nspaces = 0; + } + column = (column + tabsize) / tabsize * tabsize; + break; + + case '\r': + case '\n': + case PS: + case LS: + // Truncate any trailing spaces or tabs + if (nwhite) + { + if (!changes) + change(); + result = result[0 .. result.length - nwhite]; + } + break; + + default: + if (nspaces >= 2 && (column % tabsize) == 0) + { + if (!changes) + change(); + + int j = result.length - nspaces; + int ntabs = (nspaces + tabsize - 1) / tabsize; + result.length = j + ntabs; + result[j .. j + ntabs] = '\t'; + nwhite += ntabs - nspaces; + nspaces = 0; + } + if (c == ' ') + { nwhite++; + nspaces++; + } + else + { nwhite = 0; + nspaces = 0; + } + column++; + break; + } + if (changes) + { + if (c <= 0x7F) + result ~= c; + else + std.utf.encode(result, c); + } + } + + // Truncate any trailing spaces or tabs + if (nwhite) + result = result[0 .. result.length - nwhite]; + + return result; +} + +unittest +{ + debug(string) printf("string.entab.unittest\n"); + + char[] r; + + r = entab(null); + assert(r == null); + r = entab(""); + assert(r.length == 0); + r = entab("a"); + assert(r == "a"); + r = entab(" "); + assert(r == ""); + r = entab(" x"); + assert(r == "\tx"); + r = entab(" ab asdf "); + assert(r == " ab\tasdf"); + r = entab(" ab asdf "); + assert(r == " ab\t asdf"); + r = entab(" ab \t asdf "); + assert(r == " ab\t asdf"); + r = entab("1234567 \ta"); + assert(r == "1234567\t\ta"); + r = entab("1234567 \ta"); + assert(r == "1234567\t\ta"); + r = entab("1234567 \ta"); + assert(r == "1234567\t\ta"); + r = entab("1234567 \ta"); + assert(r == "1234567\t\ta"); + r = entab("1234567 \ta"); + assert(r == "1234567\t\ta"); + r = entab("1234567 \ta"); + assert(r == "1234567\t\ta"); + r = entab("1234567 \ta"); + assert(r == "1234567\t\ta"); + r = entab("1234567 \ta"); + assert(r == "1234567\t\ta"); + r = entab("1234567 \ta"); + assert(r == "1234567\t\t\ta"); + // TODO: need UTF test case +} + + + /************************************ * Construct translation table for translate(). * BUG: only works with ASCII @@ -3320,7 +3497,7 @@ unittest { - writefln( "isNumeric(in char[], bool = false).unittest" ); + debug (string) printf("isNumeric(in char[], bool = false).unittest\n"); char[] s; // Test the isNumeric(in char[]) function @@ -3371,3 +3548,348 @@ assert(isNumeric(-real.infinity) == true); } + +/***************************** + * Soundex algorithm. + * + * The Soundex algorithm converts a word into 4 characters + * based on how the word sounds phonetically. The idea is that + * two spellings that sound alike will have the same Soundex + * value, which means that Soundex can be used for fuzzy matching + * of names. + * + * Params: + * string = String to convert to Soundex representation. + * buffer = Optional 4 char array to put the resulting Soundex + * characters into. If null, the return value + * buffer will be allocated on the heap. + * Returns: + * The four character array with the Soundex result in it. + * Returns null if there is no Soundex representation for the string. + * + * See_Also: + * $(LINK2 http://en.wikipedia.org/wiki/Soundex, Wikipedia), + * $(LINK2 http://www.archives.gov/publications/general-info-leaflets/55.html, The Soundex Indexing System) + * + * Bugs: + * Only works well with English names. + * There are other arguably better Soundex algorithms, + * but this one is the standard one. + */ + +char[] soundex(char[] string, char[] buffer = null) +in +{ + assert(!buffer || buffer.length >= 4); +} +out (result) +{ + if (result) + { + assert(result.length == 4); + assert(result[0] >= 'A' && result[0] <= 'Z'); + foreach (char c; result[1 .. 4]) + assert(c >= '0' && c <= '6'); + } +} +body +{ + static char[26] dex = + // ABCDEFGHIJKLMNOPQRSTUVWXYZ + "01230120022455012623010202"; + + int b = 0; + char lastc; + foreach (char c; string) + { + if (c >= 'a' && c <= 'z') + c -= 'a' - 'A'; + else if (c >= 'A' && c <= 'Z') + { + ; + } + else + { lastc = lastc.init; + continue; + } + if (b == 0) + { + if (!buffer) + buffer = new char[4]; + buffer[0] = c; + b++; + lastc = dex[c - 'A']; + } + else + { + if (c == 'H' || c == 'W') + continue; + if (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U') + lastc = lastc.init; + c = dex[c - 'A']; + if (c != '0' && c != lastc) + { + buffer[b] = c; + b++; + lastc = c; + } + } + if (b == 4) + goto Lret; + } + if (b == 0) + buffer = null; + else + buffer[b .. 4] = '0'; +Lret: + return buffer; +} + +unittest +{ char[4] buffer; + + assert(soundex(null) == null); + assert(soundex("") == null); + assert(soundex("0123^&^^**&^") == null); + assert(soundex("Euler") == "E460"); + assert(soundex(" Ellery ") == "E460"); + assert(soundex("Gauss") == "G200"); + assert(soundex("Ghosh") == "G200"); + assert(soundex("Hilbert") == "H416"); + assert(soundex("Heilbronn") == "H416"); + assert(soundex("Knuth") == "K530"); + assert(soundex("Kant", buffer) == "K530"); + assert(soundex("Lloyd") == "L300"); + assert(soundex("Ladd") == "L300"); + assert(soundex("Lukasiewicz", buffer) == "L222"); + assert(soundex("Lissajous") == "L222"); + assert(soundex("Robert") == "R163"); + assert(soundex("Rupert") == "R163"); + assert(soundex("Rubin") == "R150"); + assert(soundex("Washington") == "W252"); + assert(soundex("Lee") == "L000"); + assert(soundex("Gutierrez") == "G362"); + assert(soundex("Pfister") == "P236"); + assert(soundex("Jackson") == "J250"); + assert(soundex("Tymczak") == "T522"); + assert(soundex("Ashcraft") == "A261"); + + assert(soundex("Woo") == "W000"); + assert(soundex("Pilgrim") == "P426"); + assert(soundex("Flingjingwaller") == "F452"); + assert(soundex("PEARSE") == "P620"); + assert(soundex("PIERCE") == "P620"); + assert(soundex("Price") == "P620"); + assert(soundex("CATHY") == "C300"); + assert(soundex("KATHY") == "K300"); + assert(soundex("Jones") == "J520"); + assert(soundex("johnsons") == "J525"); + assert(soundex("Hardin") == "H635"); + assert(soundex("Martinez") == "M635"); +} + + +/*************************************************** + * Construct an associative array consisting of all + * abbreviations that uniquely map to the strings in values. + * + * This is useful in cases where the user is expected to type + * in one of a known set of strings, and the program will helpfully + * autocomplete the string once sufficient characters have been + * entered that uniquely identify it. + */ + +char[][char[]] abbrev(char[][] values) +{ + char[][char[]] result; + + // Make a copy when sorting so we follow COW principles. + values = values.dup.sort; + + size_t values_length = values.length; + size_t lasti = values_length; + size_t nexti; + + char[] nv; + char[] lv; + + for (size_t i = 0; i < values_length; i = nexti) + { char[] value = values[i]; + + // Skip dups + for (nexti = i + 1; nexti < values_length; nexti++) + { nv = values[nexti]; + if (value != values[nexti]) + break; + } + + for (size_t j = 0; j < value.length; j += std.utf.stride(value, j)) + { char[] v = value[0 .. j]; + + if ((nexti == values_length || j > nv.length || v != nv[0 .. j]) && + (lasti == values_length || j > lv.length || v != lv[0 .. j])) + result[v] = value; + } + result[value] = value; + lasti = i; + lv = value; + } + + return result; +} + +unittest +{ + debug(string) printf("string.abbrev.unittest\n"); + + char[][] values; + values ~= "hello"; + values ~= "hello"; + values ~= "he"; + + char[][char[]] r; + + r = abbrev(values); + char[][] keys = r.keys.dup; + keys.sort; + + assert(keys.length == 4); + assert(keys[0] == "he"); + assert(keys[1] == "hel"); + assert(keys[2] == "hell"); + assert(keys[3] == "hello"); + + assert(r[keys[0]] == "he"); + assert(r[keys[1]] == "hello"); + assert(r[keys[2]] == "hello"); + assert(r[keys[3]] == "hello"); +} + + +/****************************************** + * Compute column number after string if string starts in the + * leftmost column, which is numbered starting from 0. + */ + +int column(char[] string, int tabsize = 8) +{ + int column; + + foreach (dchar c; string) + { + switch (c) + { + case '\t': + column = (column + tabsize) / tabsize * tabsize; + break; + + case '\r': + case '\n': + case PS: + case LS: + column = 0; + break; + + default: + column++; + break; + } + } + return column; +} + +unittest +{ + debug(string) printf("string.column.unittest\n"); + + assert(column(null) == 0); + assert(column("") == 0); + assert(column("\t") == 8); + assert(column("abc\t") == 8); + assert(column("12345678\t") == 16); +} + +/****************************************** + * Wrap text into a paragraph. + */ + +char[] wrap(char[] s, int columns = 80, char[] firstindent = null, + char[] indent = null, int tabsize = 8) +{ + char[] result; + int col; + int spaces; + bool inword; + bool first = true; + size_t wordstart; + + result.length = firstindent.length + s.length; + result.length = firstindent.length; + result[] = firstindent[]; + col = column(result, tabsize); + foreach (size_t i, dchar c; s) + { + if (iswhite(c)) + { + if (inword) + { + if (first) + { + ; + } + else if (col + 1 + (i - wordstart) > columns) + { + result ~= '\n'; + result ~= indent; + col = column(indent, tabsize); + } + else + { result ~= ' '; + col += 1; + } + result ~= s[wordstart .. i]; + col += i - wordstart; + inword = false; + first = false; + } + } + else + { + if (!inword) + { + wordstart = i; + inword = true; + } + } + } + + if (inword) + { + if (col + 1 + (s.length - wordstart) >= columns) + { + result ~= '\n'; + result ~= indent; + } + else + result ~= ' '; + result ~= s[wordstart .. s.length]; + } + result ~= '\n'; + + return result; +} + +unittest +{ + debug(string) printf("string.wrap.unittest\n"); + + assert(wrap(null) == "\n"); + assert(wrap(" a b df ") == "a b df\n"); + //writefln("'%s'", wrap(" a b df ",3)); + assert(wrap(" a b df ", 3) == "a b\ndf\n"); + assert(wrap(" a bc df ", 3) == "a\nbc\ndf\n"); + //writefln("'%s'", wrap(" abcd df ",3)); + assert(wrap(" abcd df ", 3) == "abcd\ndf\n"); +} + + diff -uNr dmd-0.139/dmd/src/phobos/std/utf.d dmd-0.140/dmd/src/phobos/std/utf.d --- dmd-0.139/dmd/src/phobos/std/utf.d 2005-11-06 11:16:16.000000000 +0100 +++ dmd-0.140/dmd/src/phobos/std/utf.d 2005-11-24 17:12:54.000000000 +0100 @@ -22,17 +22,29 @@ * distribution. */ -// Description of UTF-8 at: -// http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 -// http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335 - +/******************************************** + * Encode and decode UTF-8, UTF-16 and UTF-32 strings. + * + * For Win32 systems, the C wchar_t type is UTF-16 and corresponds to the D + * wchar type. + * For linux systems, the C wchar_t type is UTF-32 and corresponds to + * the D utf.dchar type. + * + * UTF character support is restricted to (\u0000 <= character <= \U0010FFFF). + * + * See_Also: + * $(LINK2 http://en.wikipedia.org/wiki/Unicode, Wikipedia)
+ * $(LINK http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8)
+ * $(LINK http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335) + */ + module std.utf; private import std.stdio; //debug=utf; // uncomment to turn on debugging printf's -class UtfError : Error +deprecated class UtfError : Error { size_t idx; // index in string of where error occurred @@ -43,6 +55,30 @@ } } +/********************************** + * Exception class that is thrown upon any errors. + */ + +class UtfException : Exception +{ + size_t idx; /// index in string of where error occurred + + this(char[] s, size_t i) + { + idx = i; + super(s); + } +} + +/******************************* + * Test if c is a valid UTF-32 character. + * + * \uFFFE and \uFFFF are considered valid by this function, + * as they are permitted for internal use by an application, + * but they are not allowed for interchange by the Unicode standard. + * + * Returns: true if it is, false if not. + */ bit isValidDchar(dchar c) { @@ -64,12 +100,6 @@ } -/* This array gives the length of a UTF-8 sequence indexed by the value - * of the leading byte. An FF represents an illegal starting value of - * a UTF-8 sequence. - * FF is used instead of 0 to avoid having loops hang. - */ - ubyte[256] UTF8stride = [ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -90,25 +120,44 @@ 4,4,4,4,4,4,4,4,5,5,5,5,6,6,0xFF,0xFF, ]; +/** + * stride() returns the length of a UTF-8 sequence starting at index i + * in string s. + * Returns: + * The number of bytes in the UTF-8 sequence or + * 0xFF meaning s[i] is not the start of of UTF-8 sequence. + */ + uint stride(char[] s, size_t i) { return UTF8stride[s[i]]; } +/** + * stride() returns the length of a UTF-16 sequence starting at index i + * in string s. + */ + uint stride(wchar[] s, size_t i) { uint u = s[i]; return 1 + (u >= 0xD800 && u <= 0xDBFF); } +/** + * stride() returns the length of a UTF-32 sequence starting at index i + * in string s. + * Returns: The return value will always be 1. + */ + uint stride(dchar[] s, size_t i) { return 1; } /******************************************* - * Given an index into an array of char's, - * and assuming that index is at the start of a UTF character, - * determine the number of UCS characters up to that index. + * Given an index i into an array of characters s[], + * and assuming that index i is at the start of a UTF character, + * determine the number of UCS characters up to that index i. */ size_t toUCSindex(char[] s, size_t i) @@ -127,11 +176,13 @@ if (j > i) { Lerr: - throw new UtfError("1invalid UTF-8 sequence", j); + throw new UtfException("1invalid UTF-8 sequence", j); } return n; } +/** ditto */ + size_t toUCSindex(wchar[] s, size_t i) { size_t n; @@ -146,18 +197,20 @@ if (j > i) { Lerr: - throw new UtfError("2invalid UTF-16 sequence", j); + throw new UtfException("2invalid UTF-16 sequence", j); } return n; } +/** ditto */ + size_t toUCSindex(dchar[] s, size_t i) { return i; } /****************************************** - * Given a UCS index into an array of characters, return the UTF index. + * Given a UCS index n into an array of characters s[], return the UTF index. */ size_t toUTFindex(char[] s, size_t n) @@ -168,12 +221,14 @@ { uint j = UTF8stride[s[i]]; if (j == 0xFF) - throw new UtfError("3invalid UTF-8 sequence", i); + throw new UtfException("3invalid UTF-8 sequence", i); i += j; } return i; } +/** ditto */ + size_t toUTFindex(wchar[] s, size_t n) { size_t i; @@ -186,6 +241,8 @@ return i; } +/** ditto */ + size_t toUTFindex(dchar[] s, size_t n) { return n; @@ -193,6 +250,12 @@ /* =================== Decode ======================= */ +/*************** + * Decodes and returns character starting at s[idx]. idx is advanced past the + * decoded character. If the character is not well formed, a UtfException is + * thrown and idx remains unchanged. + */ + dchar decode(char[] s, inout size_t idx) in { @@ -277,7 +340,7 @@ Lerr: //printf("\ndecode: idx = %d, i = %d, length = %d s = \n'%.*s'\n%x\n'%.*s'\n", idx, i, s.length, s, s[i], s[i .. length]); - throw new UtfError("4invalid UTF-8 sequence", i); + throw new UtfException("4invalid UTF-8 sequence", i); } unittest @@ -324,7 +387,7 @@ c = decode(s4[j], i); assert(0); } - catch (UtfError u) + catch (UtfException u) { i = 23; delete u; @@ -333,7 +396,7 @@ } } -/********************************************************/ +/** ditto */ dchar decode(wchar[] s, inout size_t idx) in @@ -387,10 +450,10 @@ return cast(dchar)u; Lerr: - throw new UtfError(msg, i); + throw new UtfException(msg, i); } -/********************************************************/ +/** ditto */ dchar decode(dchar[] s, inout size_t idx) in @@ -408,12 +471,16 @@ return c; Lerr: - throw new UtfError("5invalid UTF-32 value", i); + throw new UtfException("5invalid UTF-32 value", i); } /* =================== Encode ======================= */ +/******************************* + * Encodes character c and appends it to array s[]. + */ + void encode(inout char[] s, dchar c) in { @@ -481,7 +548,7 @@ assert(s == "abcda\xC2\xA9\xE2\x89\xA0"); } -/********************************************************/ +/** ditto */ void encode(inout wchar[] s, dchar c) in @@ -507,6 +574,8 @@ s = r; } +/** ditto */ + void encode(inout dchar[] s, dchar c) in { @@ -519,6 +588,11 @@ /* =================== Validation ======================= */ +/*********************************** + * Checks to see if string is well formed or not. Throws a UtfException if it is + * not. Use to check all untrusted input for correctness. + */ + void validate(char[] s) { size_t len = s.length; @@ -530,6 +604,8 @@ } } +/** ditto */ + void validate(wchar[] s) { size_t len = s.length; @@ -541,6 +617,8 @@ } } +/** ditto */ + void validate(dchar[] s) { size_t len = s.length; @@ -593,6 +671,10 @@ } } +/******************* + * Encodes string s into UTF-8 and returns the encoded string. + */ + char[] toUTF8(char[] s) in { @@ -603,6 +685,8 @@ return s; } +/** ditto */ + char[] toUTF8(wchar[] s) { char[] r; @@ -629,6 +713,8 @@ return r; } +/** ditto */ + char[] toUTF8(dchar[] s) { char[] r; @@ -677,6 +763,12 @@ } } +/**************** + * Encodes string s into UTF-16 and returns the encoded string. + * toUTF16z() is suitable for calling the 'W' functions in the Win32 API that take + * an LPWSTR or LPCWSTR argument. + */ + wchar[] toUTF16(char[] s) { wchar[] r; @@ -701,6 +793,8 @@ return r; } +/** ditto */ + wchar* toUTF16z(char[] s) { wchar[] r; @@ -726,6 +820,8 @@ return r; } +/** ditto */ + wchar[] toUTF16(wchar[] s) in { @@ -736,6 +832,8 @@ return s; } +/** ditto */ + wchar[] toUTF16(dchar[] s) { wchar[] r; @@ -752,6 +850,10 @@ /* =================== Conversion to UTF32 ======================= */ +/***** + * Encodes string s into UTF-32 and returns the encoded string. + */ + dchar[] toUTF32(char[] s) { dchar[] r; @@ -771,6 +873,8 @@ return r[0 .. j]; } +/** ditto */ + dchar[] toUTF32(wchar[] s) { dchar[] r; @@ -790,6 +894,8 @@ return r[0 .. j]; } +/** ditto */ + dchar[] toUTF32(dchar[] s) in { diff -uNr dmd-0.139/dmd/src/phobos/std/windows/charset.d dmd-0.140/dmd/src/phobos/std/windows/charset.d --- dmd-0.139/dmd/src/phobos/std/windows/charset.d 1970-01-01 01:00:00.000000000 +0100 +++ dmd-0.140/dmd/src/phobos/std/windows/charset.d 2005-11-24 17:12:56.000000000 +0100 @@ -0,0 +1,120 @@ +/* Public Domain */ + +/** + * Support UTF-8 on Windows 95, 98 and ME systems. + */ + +module std.windows.charset; + +private import std.c.windows.windows; +private import std.windows.syserror; +private import std.utf; +private import std.string; + +/** + * If non-zero, the application should use the W versions of Windows API + * functions and std.utf.toUTF16z and toUTF8, rather than toMBSz and + * fromMBSz. + */ +int useWfuncs = 1; + +static this() +{ + // Win 95, 98, ME do not implement the W functions + // TODO: detect MSLU? + useWfuncs = (GetVersion() < 0x80000000); +} + + +/****************************************** + * Converts the UTF-8 string s into a null-terminated string in a Windows + * 8-bit character set. + * + * Params: + * s = UTF-8 string to convert. + * codePage = is the number of the target codepage, or + * 0 - ANSI, + * 1 - OEM, + * 2 - Mac + * + * Authors: + * yaneurao, Walter Bright, Stewart Gordon + */ + +char* toMBSz(char[] s, uint codePage = 0) +{ + // Only need to do this if any chars have the high bit set + foreach (char c; s) + { + if (c >= 0x80) + { + char[] result; + int readLen; + wchar* ws = std.utf.toUTF16z(s); + result.length = WideCharToMultiByte(codePage, 0, ws, -1, null, 0, + null, null); + + if (result.length) + { + readLen = WideCharToMultiByte(codePage, 0, ws, -1, result.ptr, + result.length, null, null); + } + + if (!readLen || readLen != result.length) + { + throw new Exception("Couldn't convert string: " ~ + sysErrorString(GetLastError())); + } + + return result; + } + } + return std.string.toStringz(s); +} + + +/********************************************** + * Converts the null-terminated string s from a Windows 8-bit character set + * into a UTF-8 char array. + * + * Params: + * s = UTF-8 string to convert. + * codePage = is the number of the source codepage, or + * 0 - ANSI, + * 1 - OEM, + * 2 - Mac + * Authors: Steward Gordon, Walter Bright + */ + +char[] fromMBSz(char* s, int codePage = 0) +{ + char* c; + + for (c = s; *c != 0; c++) + { + if (*c >= 0x80) + { + wchar[] result; + int readLen; + + result.length = MultiByteToWideChar(codePage, 0, s, -1, null, 0); + + if (result.length) + { + readLen = MultiByteToWideChar(codePage, 0, s, -1, result.ptr, + result.length); + } + + if (!readLen || readLen != result.length) + { + throw new Exception("Couldn't convert string: " ~ + sysErrorString(GetLastError())); + } + + return std.utf.toUTF8(result[0 .. result.length-1]); // omit trailing null + } + } + return s[0 .. c-s]; // string is ASCII, no conversion necessary +} + + diff -uNr dmd-0.139/dmd/src/phobos/std.ddoc dmd-0.140/dmd/src/phobos/std.ddoc --- dmd-0.139/dmd/src/phobos/std.ddoc 2005-11-06 11:16:16.000000000 +0100 +++ dmd-0.140/dmd/src/phobos/std.ddoc 2005-11-24 17:12:54.000000000 +0100 @@ -54,6 +54,7 @@  std.conv
 std.ctype
 std.date
std.demangle
 std.file
 std.format
 std.gc
@@ -81,6 +82,7 @@  std.utf
 std.zip
 std.zlib
std.windows.charset

std.windows

diff -uNr dmd-0.139/dmd/src/phobos/unittest.d dmd-0.140/dmd/src/phobos/unittest.d --- dmd-0.139/dmd/src/phobos/unittest.d 2005-11-06 11:16:16.000000000 +0100 +++ dmd-0.140/dmd/src/phobos/unittest.d 2005-11-24 17:12:54.000000000 +0100 @@ -37,6 +37,7 @@ import std.random; import std.date; import std.dateparse; +import std.demangle; import std.cstream; import std.stream; import std.utf; @@ -100,6 +101,8 @@ std.math.tgamma(3); std.math.lgamma(3); + std.demangle.demangle("hello"); + printf("Success\n!"); return 0; } diff -uNr dmd-0.139/dmd/src/phobos/win32.mak dmd-0.140/dmd/src/phobos/win32.mak --- dmd-0.139/dmd/src/phobos/win32.mak 2005-11-06 11:16:16.000000000 +0100 +++ dmd-0.140/dmd/src/phobos/win32.mak 2005-11-24 17:12:54.000000000 +0100 @@ -50,7 +50,7 @@ test : test.exe test.obj : test.d - $(DMD) -c test -g + $(DMD) -c test -g -unittest test.exe : test.obj phobos.lib $(DMD) test.obj -g -L/map @@ -71,8 +71,8 @@ Czlib.obj Dzlib.obj zip.obj process.obj registry.obj recls.obj \ socket.obj socketstream.obj loader.obj stdarg.obj format.obj stdio.obj \ perf.obj openrj.obj uni.obj winsock.obj oldsyserror.obj \ - errno.obj boxer.obj cstream.obj \ - realtest.obj gamma.obj \ + errno.obj boxer.obj cstream.obj charset.obj \ + realtest.obj gamma.obj demangle.obj \ ti_Aa.obj ti_Ag.obj ti_C.obj ti_int.obj ti_char.obj \ ti_wchar.obj ti_uint.obj ti_short.obj ti_ushort.obj \ ti_byte.obj ti_ubyte.obj ti_long.obj ti_ulong.obj ti_ptr.obj \ @@ -90,7 +90,10 @@ $(DOC)\std_stream.html $(DOC)\std_string.html $(DOC)\std_base64.html \ $(DOC)\object.html $(DOC)\std_compiler.html $(DOC)\std_format.html \ $(DOC)\std_random.html $(DOC)\std_file.html $(DOC)\std_date.html \ - $(DOC)\std_md5.html $(DOC)\std_zip.html $(DOC)\std_zlib.html + $(DOC)\std_md5.html $(DOC)\std_zip.html $(DOC)\std_zlib.html \ + $(DOC)\std_demangle.html \ + $(DOC)\std_utf.html \ + $(DOC)\std_windows_charset.html SRC= errno.c object.d unittest.d crc32.d gcstats.d @@ -103,7 +106,7 @@ std\regexp.d std\random.d std\stream.d std\process.d std\recls.d \ std\socket.d std\socketstream.d std\loader.d std\stdarg.d std\format.d \ std\stdio.d std\perf.d std\openrj.d std\uni.d std\boxer.d \ - std\cstream.d + std\cstream.d std\demangle.d SRC_STD_C= std\c\process.d std\c\stdlib.d std\c\time.d std\c\stdio.d \ std\c\math.d std\c\stdarg.d std\c\stddef.d @@ -143,7 +146,7 @@ internal\object.d internal\trace.d internal\qsort2.d SRC_STD_WIN= std\windows\registry.d \ - std\windows\iunknown.d std\windows\syserror.d + std\windows\iunknown.d std\windows\syserror.d std\windows\charset.d SRC_STD_C_WIN= std\c\windows\windows.d std\c\windows\com.d \ std\c\windows\winsock.d @@ -472,6 +475,9 @@ dateparse.obj : std\dateparse.d std\date.d $(DMD) -c $(DFLAGS) std\dateparse.d +demangle.obj : std\demangle.d + $(DMD) -c $(DFLAGS) std\demangle.d + file.obj : std\file.d $(DMD) -c $(DFLAGS) std\file.d @@ -573,6 +579,9 @@ ### std\windows +charset.obj : std\windows\charset.d + $(DMD) -c $(DFLAGS) std\windows\charset.d + iunknown.obj : std\windows\iunknown.d $(DMD) -c $(DFLAGS) std\windows\iunknown.d @@ -757,6 +766,9 @@ $(DOC)\std_date.html : std.ddoc std\date.d $(DMD) -c -o- $(DFLAGS) -Df$(DOC)\std_date.html std.ddoc std\date.d +$(DOC)\std_demangle.html : std.ddoc std\demangle.d + $(DMD) -c -o- $(DFLAGS) -Df$(DOC)\std_demangle.html std.ddoc std\demangle.d + $(DOC)\std_file.html : std.ddoc std\file.d $(DMD) -c -o- $(DFLAGS) -Df$(DOC)\std_file.html std.ddoc std\file.d @@ -784,12 +796,18 @@ $(DOC)\std_string.html : std.ddoc std\string.d $(DMD) -c -o- $(DFLAGS) -Df$(DOC)\std_string.html std.ddoc std\string.d +$(DOC)\std_utf.html : std.ddoc std\utf.d + $(DMD) -c -o- $(DFLAGS) -Df$(DOC)\std_utf.html std.ddoc std\utf.d + $(DOC)\std_zip.html : std.ddoc std\zip.d $(DMD) -c -o- $(DFLAGS) -Df$(DOC)\std_zip.html std.ddoc std\zip.d $(DOC)\std_zlib.html : std.ddoc std\zlib.d $(DMD) -c -o- $(DFLAGS) -Df$(DOC)\std_zlib.html std.ddoc std\zlib.d +$(DOC)\std_windows_charset.html : std.ddoc std\windows\charset.d + $(DMD) -c -o- $(DFLAGS) -Df$(DOC)\std_windows_charset.html std.ddoc std\windows\charset.d + $(DOC)\object.html : std.ddoc internal\object.d $(DMD) -c -o- $(DFLAGS) -Df$(DOC)\object.html std.ddoc internal\object.d