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