diff -uNr dmd-0.125/dmd/src/dmd/aggregate.h dmd-0.126/dmd/src/dmd/aggregate.h --- dmd-0.125/dmd/src/dmd/aggregate.h 2005-05-06 21:28:54.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/aggregate.h 2005-06-03 01:21:54.000000000 +0200 @@ -36,6 +36,7 @@ struct AggregateDeclaration : ScopeDsymbol { Type *type; + unsigned storage_class; Type *handle; // 'this' type unsigned structsize; // size of struct unsigned alignsize; // size of struct for alignment purposes @@ -158,6 +159,9 @@ int isauto; // !=0 if this is an auto class int isabstract; // !=0 if abstract class + int isnested; // !=0 if is nested + VarDeclaration *vthis; // 'this' parameter if this class is nested + ClassDeclaration(Loc loc, Identifier *id, Array *baseclasses); Dsymbol *syntaxCopy(Dsymbol *s); void semantic(Scope *sc); @@ -170,6 +174,7 @@ Dsymbol *search(Identifier *ident, int flags); FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf); void interfaceSemantic(Scope *sc); + int isNested(); int isCOMclass(); int isAbstract(); virtual int vtblOffset(); diff -uNr dmd-0.125/dmd/src/dmd/class.c dmd-0.126/dmd/src/dmd/class.c --- dmd-0.125/dmd/src/dmd/class.c 2005-05-20 11:09:24.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/class.c 2005-06-06 14:55:44.000000000 +0200 @@ -112,6 +112,8 @@ #endif isauto = 0; isabstract = 0; + isnested = 0; + vthis = NULL; } Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s) @@ -124,6 +126,8 @@ else cd = new ClassDeclaration(loc, ident, NULL); + cd->storage_class |= storage_class; + cd->baseclasses.setDim(this->baseclasses.dim); for (int i = 0; i < cd->baseclasses.dim; i++) { @@ -142,9 +146,16 @@ //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this); //printf("parent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : ""); + //printf("sc->stc = %x\n", sc->stc); //{ static int n; if (++n == 20) *(char*)0=0; } + if (!ident) // if anonymous class + { char *id = "__anonclass"; + + ident = Identifier::generateId(id); + } + if (!scope) { if (!parent && sc->parent && !sc->parent->isModule()) @@ -293,6 +304,7 @@ // Inherit properties from base class com = baseClass->isCOMclass(); isauto = baseClass->isauto; + vthis = baseClass->vthis; } else { @@ -301,6 +313,8 @@ vtbl.push(this); // leave room for classinfo as first member } + storage_class |= sc->stc; + if (sizeok == 0) { interfaceSemantic(sc); @@ -310,13 +324,50 @@ Dsymbol *s = (Dsymbol *)members->data[i]; s->addMember(sc, this); } + + /* If this is a nested class, add the hidden 'this' + * member which is a pointer to the enclosing scope. + */ + if (vthis) // if inheriting from nested class + { // Use the base class's 'this' member + isnested = 1; + if (storage_class & STCstatic) + error("static class cannot inherit from nested class %s", baseClass->toChars()); + if (toParent() != baseClass->toParent()) + error("super class %s is nested within %s, not %s", + baseClass->toChars(), + baseClass->toParent()->toChars(), + toParent()->toChars()); + } + else if (!(storage_class & STCstatic)) + { Dsymbol *s = toParent(); + ClassDeclaration *cd = s->isClassDeclaration(); + FuncDeclaration *fd = s->isFuncDeclaration(); + + + if (cd || fd) + { isnested = 1; + Type *t; + if (cd) + t = cd->type; + else if (fd) + { t = new TypePointer(Type::tvoid); + t = t->semantic(0, sc); + } + else + assert(0); + assert(!vthis); + vthis = new ThisDeclaration(t); + members->push(vthis); + } + } } - if (sc->stc & STCauto) + if (storage_class & STCauto) isauto = 1; - if (sc->stc & STCabstract) + if (storage_class & STCabstract) isabstract = 1; - if (sc->stc & STCdeprecated) + if (storage_class & STCdeprecated) isdeprecated = 1; sc = sc->push(this); @@ -331,6 +382,8 @@ if (baseClass) { sc->offset = baseClass->structsize; alignsize = baseClass->alignsize; +// if (isnested) +// sc->offset += PTRSIZE; // room for uplevel context pointer } else { sc->offset = 8; // allow room for vptr[] and monitor @@ -651,6 +704,16 @@ } /**************************************** + * Returns !=0 if there's an extra member which is the 'this' + * pointer to the enclosing context (enclosing class or function) + */ + +int ClassDeclaration::isNested() +{ + return isnested; +} + +/**************************************** * Determine if slot 0 of the vtbl[] is reserved for something else. * For class objects, yes, this is where the classinfo ptr goes. * For COM interfaces, no. diff -uNr dmd-0.125/dmd/src/dmd/cond.c dmd-0.126/dmd/src/dmd/cond.c --- dmd-0.125/dmd/src/dmd/cond.c 2005-05-20 01:00:28.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/cond.c 2005-05-26 17:20:04.000000000 +0200 @@ -18,6 +18,7 @@ #include "cond.h" #include "module.h" #include "template.h" +#include "lexer.h" int findCondition(Array *ids, Identifier *ident) { @@ -210,7 +211,11 @@ return 0; } + sc = sc->push(); + sc->sd = s; + sc->flags |= SCOPEstaticif; Expression *e = exp->semantic(sc); + sc->pop(); e = e->optimize(WANTvalue); if (e->isBool(TRUE)) inc = 1; @@ -235,11 +240,12 @@ /**************************** IftypeCondition *******************************/ -IftypeCondition::IftypeCondition(Loc loc, Type *targ, Identifier *id, Type *tspec) +IftypeCondition::IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec) : Condition(loc) { this->targ = targ; this->id = id; + this->tok = tok; this->tspec = tspec; } @@ -248,6 +254,7 @@ return new IftypeCondition(loc, targ->syntaxCopy(), id, + tok, tspec ? tspec->syntaxCopy() : NULL); } @@ -262,9 +269,15 @@ inc = 2; return 0; } + unsigned errors = global.errors; + global.gag++; // suppress printing of error messages targ = targ->semantic(loc, sc); - - if (id && tspec) + global.gag--; + if (errors != global.errors) // if any errors happened + { inc = 2; // then condition is false + global.errors = errors; + } + else if (id && tspec) { /* Evaluate to TRUE if targ matches tspec. * If TRUE, declare id as an alias for the specialized type. @@ -281,7 +294,8 @@ dedtypes.setDim(1); m = targ->deduceType(tspec, ¶meters, &dedtypes); - if (m == MATCHnomatch) + if (m == MATCHnomatch || + (m != MATCHexact && tok == TOKequal)) inc = 2; else { @@ -314,14 +328,21 @@ tspec = tspec->semantic(loc, sc); //printf("targ = %s\n", targ->toChars()); //printf("tspec = %s\n", tspec->toChars()); - //if (targ->equals(tspec)) - if (targ->implicitConvTo(tspec)) - inc = 1; - else - inc = 2; + if (tok == TOKcolon) + { if (targ->implicitConvTo(tspec)) + inc = 1; + else + inc = 2; + } + else /* == */ + { if (targ->equals(tspec)) + inc = 1; + else + inc = 2; + } } else - assert(0); + inc = 1; //printf("inc = %d\n", inc); } return (inc == 1); @@ -333,7 +354,10 @@ targ->toCBuffer(buf, id); if (tspec) { - buf->writestring(" : "); + if (tok == TOKcolon) + buf->writestring(" : "); + else + buf->writestring(" == "); tspec->toCBuffer(buf, NULL); } buf->writeByte(')'); diff -uNr dmd-0.125/dmd/src/dmd/cond.h dmd-0.126/dmd/src/dmd/cond.h --- dmd-0.125/dmd/src/dmd/cond.h 2005-05-15 11:54:40.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/cond.h 2005-05-25 13:11:24.000000000 +0200 @@ -16,6 +16,7 @@ struct Module; struct Scope; struct ScopeDsymbol; +enum TOK; struct Condition { @@ -79,14 +80,15 @@ struct IftypeCondition : Condition { - /* iftype (targ id : tspec) + /* iftype (targ id tok tspec) */ Loc loc; Type *targ; Identifier *id; // can be NULL + enum TOK tok; // ':' or '==' Type *tspec; // can be NULL - IftypeCondition(Loc loc, Type *targ, Identifier *id, Type *tspec); + IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec); Condition *syntaxCopy(); int include(Scope *sc, ScopeDsymbol *s); void toCBuffer(OutBuffer *buf); diff -uNr dmd-0.125/dmd/src/dmd/declaration.c dmd-0.126/dmd/src/dmd/declaration.c --- dmd-0.125/dmd/src/dmd/declaration.c 2005-05-14 13:13:42.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/declaration.c 2005-06-01 13:48:00.000000000 +0200 @@ -519,7 +519,7 @@ } // If inside function, there is no semantic3() call - if (sc->func && init) + if (sc->func && init && !init->isVoidInitializer()) { // If local variable, use AssignExp to handle all the various // possibilities. diff -uNr dmd-0.125/dmd/src/dmd/declaration.h dmd-0.126/dmd/src/dmd/declaration.h --- dmd-0.125/dmd/src/dmd/declaration.h 2005-05-18 22:34:34.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/declaration.h 2005-05-22 02:14:34.000000000 +0200 @@ -50,6 +50,7 @@ STCout = 0x1000, // out parameter STCforeach = 0x2000, // variable for foreach loop STCcomdat = 0x4000, // should go into COMDAT record + STCvariadic = 0x8000, // variadic function argument }; struct Match diff -uNr dmd-0.125/dmd/src/dmd/dsymbol.c dmd-0.126/dmd/src/dmd/dsymbol.c --- dmd-0.125/dmd/src/dmd/dsymbol.c 2005-05-12 18:44:32.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/dsymbol.c 2005-05-25 21:49:54.000000000 +0200 @@ -288,25 +288,27 @@ void Dsymbol::error(const char *format, ...) { //printf("Dsymbol::error()\n"); - char *p = locToChars(); - - if (*p) - printf("%s: ", p); - mem.free(p); + if (!global.gag) + { + char *p = locToChars(); - if (isAnonymous()) - printf("%s ", kind()); - else - printf("%s %s ", kind(), toPrettyChars()); + if (*p) + printf("%s: ", p); + mem.free(p); - va_list ap; - va_start(ap, format); - vprintf(format, ap); - va_end(ap); + if (isAnonymous()) + printf("%s ", kind()); + else + printf("%s %s ", kind(), toPrettyChars()); - printf("\n"); - fflush(stdout); + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + printf("\n"); + fflush(stdout); + } global.errors++; //fatal(); @@ -314,23 +316,26 @@ void Dsymbol::error(Loc loc, const char *format, ...) { - char *p = loc.toChars(); - if (!*p) - p = locToChars(); - - if (*p) - printf("%s: ", p); - mem.free(p); - - printf("%s %s ", kind(), toPrettyChars()); - - va_list ap; - va_start(ap, format); - vprintf(format, ap); - va_end(ap); + if (!global.gag) + { + char *p = loc.toChars(); + if (!*p) + p = locToChars(); + + if (*p) + printf("%s: ", p); + mem.free(p); + + printf("%s %s ", kind(), toPrettyChars()); - printf("\n"); - fflush(stdout); + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + + printf("\n"); + fflush(stdout); + } global.errors++; diff -uNr dmd-0.125/dmd/src/dmd/expression.c dmd-0.126/dmd/src/dmd/expression.c --- dmd-0.125/dmd/src/dmd/expression.c 2005-05-20 01:00:08.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/expression.c 2005-06-07 20:31:24.000000000 +0200 @@ -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 @@ -173,17 +173,20 @@ unsigned nargs; unsigned nproto; unsigned n; + int done; Type *tb; + //printf("functionArguments()\n"); assert(arguments); nargs = arguments ? arguments->dim : 0; nproto = tf->arguments ? tf->arguments->dim : 0; - if (nargs > nproto && !tf->varargs) + if (nargs > nproto && tf->varargs == 0) error(loc, "expected %d arguments, not %d\n", nproto, nargs); n = (nargs > nproto) ? nargs : nproto; // maximum + done = 0; for (int i = 0; i < n; i++) { Expression *arg; @@ -191,21 +194,90 @@ if (i < nargs) arg = (Expression *)arguments->data[i]; + else + arg = NULL; if (i < nproto) { Argument *p = (Argument *)tf->arguments->data[i]; - if (i >= nargs) + if (!arg) { if (!p->defaultArg) - { error(loc, "expected %d arguments, not %d\n", nproto, nargs); + { + if (tf->varargs == 2 && i + 1 == nproto) + goto L2; + error(loc, "expected %d arguments, not %d\n", nproto, nargs); break; } arg = p->defaultArg->copy(); arguments->push(arg); + nargs++; + } + + if (tf->varargs == 2 && i + 1 == nproto) + { + //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars()); + if (arg->implicitConvTo(p->type)) + { + if (nargs != nproto) + error(loc, "expected %d arguments, not %d\n", nproto, nargs); + goto L1; + } + L2: + Type *tb = p->type->toBasetype(); + switch (tb->ty) + { + case Tsarray: + case Tarray: + { // Create a static array variable v of type arg->type + Identifier *id = Lexer::idPool("__arrayArg"); + Type *t = new TypeSArray(tb->next, new IntegerExp(nargs - i)); + t = t->semantic(loc, sc); + VarDeclaration *v = new VarDeclaration(loc, t, id, NULL); + v->semantic(sc); + v->parent = sc->parent; + //sc->insert(v); + + Expression *c = NULL; + + for (int u = i; u < nargs; u++) + { Expression *a = (Expression *)arguments->data[u]; + Expression *e = new VarExp(loc, v); + + e = new IndexExp(loc, e, new IntegerExp(u + 1 - nproto)); + e = new AssignExp(loc, e, a); + if (c) + c = new CommaExp(loc, c, e); + else + c = e; + } + arg = new VarExp(loc, v); + if (c) + arg = new CommaExp(loc, c, arg); + break; + } + case Tclass: + { /* Set arg to be: + * new Tclass(arg0, arg1, ..., argn) + */ + Array *args = new Array(); + args->setDim(nargs - i); + for (int u = i; u < nargs; u++) + args->data[u - i] = arguments->data[u]; + arg = new NewExp(loc, NULL, p->type, args); + break; + } + default: + assert(0); + } + arg = arg->semantic(sc); + //printf("\targ = '%s'\n", arg->toChars()); + arguments->setDim(i + 1); + done = 1; } + L1: arg = arg->implicitCastTo(p->type); if (p->inout == Out || p->inout == InOut) { @@ -258,10 +330,12 @@ } arg = arg->optimize(WANTvalue); arguments->data[i] = (void *) arg; + if (done) + break; } // If D linkage and variadic, add _arguments[] as first argument - if (tf->linkage == LINKd && tf->varargs) + if (tf->linkage == LINKd && tf->varargs == 1) { Expression *e; @@ -350,19 +424,22 @@ void Expression::error(const char *format, ...) { - char *p = loc.toChars(); + if (!global.gag) + { + char *p = loc.toChars(); - if (*p) - printf("%s: ", p); - mem.free(p); - - va_list ap; - va_start(ap, format); - vprintf(format, ap); - va_end(ap); + if (*p) + printf("%s: ", p); + mem.free(p); - printf("\n"); - fflush(stdout); + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + + printf("\n"); + fflush(stdout); + } global.errors++; //fatal(); @@ -446,6 +523,15 @@ return toLvalue(e); } +/************************************ + * Detect cases where pointers to the stack can 'escape' the + * lifetime of the stack frame. + */ + +void Expression::checkEscape() +{ +} + void Expression::checkScalar() { if (!type->isscalar()) @@ -1215,7 +1301,7 @@ } fdthis = sc->parent->isFuncDeclaration(); - fd = hasThis(sc); + fd = hasThis(sc); // fd is the uplevel function with the 'this' variable if (!fd) goto Lerr; @@ -1229,6 +1315,7 @@ fd->vthis->nestedref = 1; fd->nestedFrameRef = 1; } + sc->callSuper |= CSXthis; return this; @@ -1686,6 +1773,19 @@ if (cd->isAbstract()) error("cannot create instance of abstract class %s", cd->toChars()); checkDeprecated(sc, cd); + if (cd->isNested()) + { /* We need a 'this' pointer for the nested class. + * Ensure we have the right one. + */ + Dsymbol *s = cd->toParent(); + ClassDeclaration *cdn = s->isClassDeclaration(); + + if (cdn) + { + if (sc->func->isThis() != cdn) + error("no 'this' for nested class %s", cd->toChars()); + } + } f = cd->ctor; if (f) { @@ -1735,7 +1835,6 @@ } } -#if 1 else if (tb->ty == Tstruct) { TypeStruct *ts = (TypeStruct *)tb; @@ -1769,7 +1868,6 @@ type = type->pointerTo(); } -#endif else if (tb->ty == Tarray && (arguments && arguments->dim)) { Expression *arg; @@ -1815,6 +1913,61 @@ } } +/********************** NewAnonClassExp **************************************/ + +NewAnonClassExp::NewAnonClassExp(Loc loc, Array *newargs, ClassDeclaration *cd, Array *arguments) + : Expression(loc, TOKnewanonclass, sizeof(NewAnonClassExp)) +{ + this->newargs = newargs; + this->cd = cd; + this->arguments = arguments; +} + +Expression *NewAnonClassExp::syntaxCopy() +{ + return new NewAnonClassExp(loc, + arraySyntaxCopy(newargs), + (ClassDeclaration *)cd->syntaxCopy(NULL), + arraySyntaxCopy(arguments)); +} + + +Expression *NewAnonClassExp::semantic(Scope *sc) +{ +#if LOGSEMANTIC + printf("NewAnonClassExp::semantic() %s\n", toChars()); + //printf("type: %s\n", type->toChars()); +#endif + + Expression *d = new DeclarationExp(loc, cd); + d = d->semantic(sc); + + Expression *n = new NewExp(loc, newargs, cd->type, arguments); + + Expression *c = new CommaExp(loc, d, n); + return c->semantic(sc); +} + +void NewAnonClassExp::toCBuffer(OutBuffer *buf) +{ int i; + + buf->writestring("new"); + if (newargs && newargs->dim) + { + buf->writeByte('('); + argsToCBuffer(buf, newargs); + buf->writeByte(')'); + } + buf->writestring(" class"); + if (arguments && arguments->dim) + { + buf->writeByte('('); + argsToCBuffer(buf, arguments); + buf->writeByte(')'); + } + buf->writestring(" { }"); +} + /********************** SymOffExp **************************************/ SymOffExp::SymOffExp(Loc loc, Declaration *var, unsigned offset) @@ -1840,6 +1993,16 @@ return result ? TRUE : FALSE; } +void SymOffExp::checkEscape() +{ + VarDeclaration *v = var->isVarDeclaration(); + if (v) + { + if (!v->isDataseg()) + error("escaping reference to local %s", v->toChars()); + } +} + void SymOffExp::toCBuffer(OutBuffer *buf) { if (offset) @@ -1896,9 +2059,8 @@ FuncDeclaration *fdthis = sc->parent->isFuncDeclaration(); if (fdv && fdthis) - { int level; - - level = fdthis->getLevel(loc, fdv); + { + fdthis->getLevel(loc, fdv); // check for access v->nestedref = 1; fdv->nestedFrameRef = 1; } @@ -1925,6 +2087,18 @@ buf->writestring(var->toChars()); } +void VarExp::checkEscape() +{ + VarDeclaration *v = var->isVarDeclaration(); + if (v) + { + if (v->isAuto() && !v->noauto) + error("escaping reference to auto local %s", v->toChars()); + else if (v->storage_class & STCvariadic) + error("escaping reference to variadic parameter %s", v->toChars()); + } +} + Expression *VarExp::toLvalue(Expression *e) { #if 0 @@ -2139,6 +2313,196 @@ /************************************************************/ +IftypeExp::IftypeExp(Loc loc, Type *targ, Identifier *id, enum TOK tok, + Type *tspec, enum TOK tok2) + : Expression(loc, TOKis, sizeof(IftypeExp)) +{ + this->targ = targ; + this->id = id; + this->tok = tok; + this->tspec = tspec; + this->tok2 = tok2; +} + +Expression *IftypeExp::syntaxCopy() +{ + return new IftypeExp(loc, + targ->syntaxCopy(), + id, + tok, + tspec ? tspec->syntaxCopy() : NULL, + tok2); +} + +Expression *IftypeExp::semantic(Scope *sc) +{ Type *tded; + + if (id && !(sc->flags & SCOPEstaticif)) + error("can only declare type aliases within static if conditionals"); + + unsigned errors = global.errors; + global.gag++; // suppress printing of error messages + targ = targ->semantic(loc, sc); + global.gag--; + if (errors != global.errors) // if any errors happened + { // then condition is false + global.errors = errors; + goto Lno; + } + else if (tok2 != TOKreserved) + { + switch (tok2) + { + case TOKtypedef: + if (targ->ty != Ttypedef) + goto Lno; + tded = ((TypeTypedef *)targ)->sym->basetype; + break; + + case TOKstruct: + if (targ->ty != Tstruct) + goto Lno; + if (((TypeStruct *)targ)->sym->isUnionDeclaration()) + goto Lno; + tded = targ; + break; + + case TOKunion: + if (targ->ty != Tstruct) + goto Lno; + if (!((TypeStruct *)targ)->sym->isUnionDeclaration()) + goto Lno; + tded = targ; + break; + + case TOKclass: + if (targ->ty != Tclass) + goto Lno; + if (((TypeClass *)targ)->sym->isInterfaceDeclaration()) + goto Lno; + tded = targ; + break; + + case TOKinterface: + if (targ->ty != Tclass) + goto Lno; + if (!((TypeClass *)targ)->sym->isInterfaceDeclaration()) + goto Lno; + tded = targ; + break; + + case TOKenum: + if (targ->ty != Tenum) + goto Lno; + tded = ((TypeEnum *)targ)->sym->memtype; + break; + + case TOKfunction: + if (targ->ty != Tfunction) + goto Lno; + tded = targ->next; + break; + + case TOKdelegate: + if (targ->ty != Tdelegate) + goto Lno; + tded = targ->next; + break; + + default: + assert(0); + } + goto Lyes; + } + else if (id && tspec) + { + /* Evaluate to TRUE if targ matches tspec. + * If TRUE, declare id as an alias for the specialized type. + */ + + MATCH m; + TemplateTypeParameter tp(loc, id, NULL, NULL); + + Array parameters; + parameters.setDim(1); + parameters.data[0] = (void *)&tp; + + Array dedtypes; + dedtypes.setDim(1); + + m = targ->deduceType(tspec, ¶meters, &dedtypes); + if (m == MATCHnomatch || + (m != MATCHexact && tok == TOKequal)) + goto Lno; + else + { + tded = (Type *)dedtypes.data[0]; + if (!tded) + tded = targ; + goto Lyes; + } + } + else if (id) + { + /* Declare id as an alias for type targ. Evaluate to TRUE + */ + tded = targ; + goto Lyes; + } + else if (tspec) + { + /* Evaluate to TRUE if targ matches tspec + */ + tspec = tspec->semantic(loc, sc); + //printf("targ = %s\n", targ->toChars()); + //printf("tspec = %s\n", tspec->toChars()); + if (tok == TOKcolon) + { if (targ->implicitConvTo(tspec)) + goto Lyes; + else + goto Lno; + } + else /* == */ + { if (targ->equals(tspec)) + goto Lyes; + else + goto Lno; + } + } + +Lyes: + if (id) + { + Dsymbol *s = new AliasDeclaration(loc, id, tded); + s->semantic(sc); + sc->insert(s); + if (sc->sd) + s->addMember(sc, sc->sd); + } + return new IntegerExp(1); + +Lno: + return new IntegerExp(0); +} + +void IftypeExp::toCBuffer(OutBuffer *buf) +{ + buf->writestring("is("); + targ->toCBuffer(buf, id); + if (tspec) + { + if (tok == TOKcolon) + buf->writestring(" : "); + else + buf->writestring(" == "); + tspec->toCBuffer(buf, NULL); + } + buf->writeByte(')'); +} + + +/************************************************************/ + UnaExp::UnaExp(Loc loc, enum TOK op, int size, Expression *e1) : Expression(loc, op, size) { @@ -2557,22 +2921,34 @@ type = var->type; assert(type); - if (!var->isFuncDeclaration()) // do checks after overload resolution + if (!var->isFuncDeclaration()) // for functions, do checks after overload resolution { - AggregateDeclaration *ad = var->parent->isAggregateDeclaration(); + AggregateDeclaration *ad = var->toParent()->isAggregateDeclaration(); + L1: Type *t = e1->type; - if (ad && !(t->ty == Tpointer && t->next->ty == Tstruct && - ((TypeStruct *)t->next)->sym == ad)) + if (ad && + !(t->ty == Tpointer && t->next->ty == Tstruct && + ((TypeStruct *)t->next)->sym == ad) + ) { ClassDeclaration *cd = ad->isClassDeclaration(); + ClassDeclaration *tcd = t->isClassHandle(); - if (!cd || - t->ty != Tclass || - !(((TypeClass *)t)->sym == cd || cd->isBaseOf(((TypeClass *)t)->sym, NULL)) + if (!cd || !tcd || + !(tcd == cd || cd->isBaseOf(tcd, NULL)) ) + { + if (tcd && tcd->isNested()) + { // Try again with outer scope + + e1 = new DotVarExp(loc, e1, tcd->vthis); + e1 = e1->semantic(sc); + goto L1; + } error("this for %s needs to be type %s not type %s", var->toChars(), ad->toChars(), t->toChars()); + } } accessCheck(loc, sc, e1, var); } @@ -2863,7 +3239,10 @@ } #endif - // Transform array.id(args) into id(array,args) + /* Transform: + * array.id(args) into id(array,args) + * aa.remove(arg) into delete aa[arg] + */ if (e1->op == TOKdot) { // BUG: we should handle array.a.b.c.e(args) too @@ -2874,7 +3253,24 @@ if (dotid->e1->type) { TY e1ty = dotid->e1->type->toBasetype()->ty; - if (e1ty == Tarray || e1ty == Tsarray || e1ty == Taarray) + if (e1ty == Taarray && dotid->ident == Id::remove) + { + if (!arguments || arguments->dim != 1) + { error("expected key as argument to aa.remove()"); + goto Lagain; + } + Expression *key = (Expression *)arguments->data[0]; + key = key->semantic(sc); + key = resolveProperties(sc, key); + key->rvalue(); + + TypeAArray *taa = (TypeAArray *)dotid->e1->type->toBasetype(); + key = key->implicitCastTo(taa->index); + key = key->implicitCastTo(taa->key); + + return new RemoveExp(loc, dotid->e1, key); + } + else if (e1ty == Tarray || e1ty == Tsarray || e1ty == Taarray) { if (!arguments) arguments = new Array(); @@ -2952,6 +3348,41 @@ f = dve->var->isFuncDeclaration(); assert(f); f = f->overloadResolve(loc, arguments); + + /* Now that we have the right function f, we need to get the + * right 'this' pointer if f is in an outer class, but our + * existing 'this' pointer is in an inner class. + * This code is analogous to that used for variables + * in DotVarExp::semantic(). + */ + AggregateDeclaration *ad = f->toParent()->isAggregateDeclaration(); + L10: + Type *t = dve->e1->type; + if (f->needThis() && ad && + !(t->ty == Tpointer && t->next->ty == Tstruct && + ((TypeStruct *)t->next)->sym == ad) && + !(t->ty == Tstruct && ((TypeStruct *)t)->sym == ad) + ) + { + ClassDeclaration *cd = ad->isClassDeclaration(); + ClassDeclaration *tcd = t->isClassHandle(); + + if (!cd || !tcd || + !(tcd == cd || cd->isBaseOf(tcd, NULL)) + ) + { + if (tcd && tcd->isNested()) + { // Try again with outer scope + + dve->e1 = new DotVarExp(loc, dve->e1, tcd->vthis); + dve->e1 = dve->e1->semantic(sc); + goto L10; + } + error("this for %s needs to be type %s not type %s", + f->toChars(), ad->toChars(), t->toChars()); + } + } + checkDeprecated(sc, f); accessCheck(loc, sc, dve->e1, f); if (!f->needThis()) @@ -3442,6 +3873,8 @@ default: if (e1->op == TOKindex) { + if (!global.params.useDeprecated) + error("delete aa[key] deprecated, use aa.remove(key)"); IndexExp *ae = (IndexExp *)(e1); Type *tb1 = ae->e1->type->toBasetype(); if (tb1->ty == Taarray) @@ -3629,6 +4062,11 @@ return e; } +void SliceExp::checkEscape() +{ + e1->checkEscape(); +} + Expression *SliceExp::toLvalue(Expression *e) { return this; @@ -3793,6 +4231,11 @@ return this; } +void CommaExp::checkEscape() +{ + e2->checkEscape(); +} + Expression *CommaExp::toLvalue(Expression *e) { e2 = e2->toLvalue(NULL); @@ -3812,6 +4255,7 @@ : BinExp(loc, TOKindex, sizeof(IndexExp), e1, e2) { lengthVar = NULL; + modifiable = 0; // assume it is an rvalue } Expression *IndexExp::semantic(Scope *sc) @@ -3887,7 +4331,6 @@ case Taarray: { TypeAArray *taa = (TypeAArray *)t1; - e1 = e1->modifiableLvalue(sc, e1); e2 = e2->implicitCastTo(taa->index); // type checking e2 = e2->implicitCastTo(taa->key); // actual argument type type = taa->next; @@ -3910,6 +4353,14 @@ return this; } +Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e) +{ + modifiable = 1; + if (e1->type->toBasetype()->ty == Taarray) + e1 = e1->modifiableLvalue(sc, e1); + return toLvalue(e); +} + void IndexExp::toCBuffer(OutBuffer *buf) { e1->toCBuffer(buf); @@ -5211,6 +5662,17 @@ /************************************************************/ +/* This deletes the key e1 from the associative array e2 + */ + +RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2) + : BinExp(loc, TOKremove, sizeof(RemoveExp), e1, e2) +{ + type = Type::tvoid; +} + +/************************************************************/ + CmpExp::CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) : BinExp(loc, op, sizeof(CmpExp), e1, e2) { @@ -5457,6 +5919,13 @@ return e; } +void CondExp::checkEscape() +{ + e1->checkEscape(); + e2->checkEscape(); +} + + Expression *CondExp::checkToBoolean() { e1 = e1->checkToBoolean(); diff -uNr dmd-0.125/dmd/src/dmd/expression.h dmd-0.126/dmd/src/dmd/expression.h --- dmd-0.125/dmd/src/dmd/expression.h 2005-05-09 16:53:06.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/expression.h 2005-06-06 14:58:16.000000000 +0200 @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2002 by Digital Mars +// Copyright (c) 1999-2005 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com @@ -33,6 +33,7 @@ struct Declaration; struct AggregateDeclaration; struct TemplateInstance; +struct ClassDeclaration; // Back end struct IRState; @@ -77,6 +78,7 @@ Expression *implicitCastTo(Type *t); virtual int implicitConvTo(Type *t); virtual Expression *castTo(Type *t); + virtual void checkEscape(); void checkScalar(); Expression *checkIntegral(); void checkArithmetic(); @@ -327,6 +329,18 @@ //Expression *inlineScan(InlineScanState *iss); }; +struct NewAnonClassExp : Expression +{ + Array *newargs; // Array of Expression's to call new operator + Array *arguments; // Array of Expression's to call class constructor + ClassDeclaration *cd; // class being instantiated + + NewAnonClassExp(Loc loc, Array *newargs, ClassDeclaration *cd, Array *arguments); + Expression *syntaxCopy(); + Expression *semantic(Scope *sc); + void toCBuffer(OutBuffer *buf); +}; + // Offset from symbol struct SymOffExp : Expression @@ -336,6 +350,7 @@ SymOffExp(Loc loc, Declaration *var, unsigned offset); Expression *semantic(Scope *sc); + void checkEscape(); void toCBuffer(OutBuffer *buf); int isConst(); int isBool(int result); @@ -357,6 +372,7 @@ void dump(int indent); char *toChars(); void toCBuffer(OutBuffer *buf); + void checkEscape(); Expression *toLvalue(Expression *e); Expression *modifiableLvalue(Scope *sc, Expression *e); elem *toElem(IRState *irs); @@ -421,6 +437,23 @@ elem *toElem(IRState *irs); }; +struct IftypeExp : Expression +{ + /* is(targ id tok tspec) + * is(targ id == tok2) + */ + Type *targ; + Identifier *id; // can be NULL + enum TOK tok; // ':' or '==' + Type *tspec; // can be NULL + enum TOK tok2; // 'struct', 'union', 'typedef', etc. + + IftypeExp(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec, enum TOK tok2); + Expression *syntaxCopy(); + Expression *semantic(Scope *sc); + void toCBuffer(OutBuffer *buf); +}; + /****************************************************************/ struct UnaExp : Expression @@ -671,6 +704,7 @@ SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr); Expression *syntaxCopy(); Expression *semantic(Scope *sc); + void checkEscape(); Expression *toLvalue(Expression *e); Expression *modifiableLvalue(Scope *sc, Expression *e); void toCBuffer(OutBuffer *buf); @@ -722,6 +756,7 @@ { CommaExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); + void checkEscape(); Expression *toLvalue(Expression *e); int isBool(int result); Expression *optimize(int result); @@ -731,10 +766,12 @@ struct IndexExp : BinExp { VarDeclaration *lengthVar; + int modifiable; IndexExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *toLvalue(Expression *e); + Expression *modifiableLvalue(Scope *sc, Expression *e); void toCBuffer(OutBuffer *buf); Expression *doInline(InlineDoState *ids); @@ -1105,6 +1142,12 @@ elem *toElem(IRState *irs); }; +struct RemoveExp : BinExp +{ + RemoveExp(Loc loc, Expression *e1, Expression *e2); + elem *toElem(IRState *irs); +}; + // == and != struct EqualExp : BinExp @@ -1143,6 +1186,7 @@ Expression *semantic(Scope *sc); Expression *optimize(int result); Expression *constFold(); + void checkEscape(); Expression *toLvalue(Expression *e); Expression *checkToBoolean(); void toCBuffer(OutBuffer *buf); diff -uNr dmd-0.125/dmd/src/dmd/func.c dmd-0.126/dmd/src/dmd/func.c --- dmd-0.125/dmd/src/dmd/func.c 2005-05-05 20:27:56.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/func.c 2005-06-05 10:09:34.000000000 +0200 @@ -440,7 +440,7 @@ } // Declare hidden variable _arguments[] and _argptr - if (f->varargs) + if (f->varargs == 1) { Type *t; if (f->linkage == LINKd) @@ -479,6 +479,8 @@ { v = new VarDeclaration(0, arg->type, arg->ident, NULL); v->storage_class |= STCparameter; + if (f->varargs == 2 && i + 1 == f->arguments->dim) + v->storage_class |= STCvariadic; switch (arg->inout) { case In: v->storage_class |= STCin; break; case Out: v->storage_class |= STCout; break; @@ -1133,27 +1135,43 @@ int FuncDeclaration::getLevel(Loc loc, FuncDeclaration *fd) { int level; - FuncDeclaration *thisfd; Dsymbol *s; Dsymbol *fdparent; + //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars()); fdparent = fd->toParent(); if (fdparent == this) return -1; - thisfd = this; + s = this; level = 0; - while (fd != thisfd && fdparent != thisfd->toParent()) + while (fd != s && fdparent != s->toParent()) { - if (!thisfd || !thisfd->isNested()) + //printf("\ts = '%s'\n", s->toChars()); + FuncDeclaration *thisfd = s->isFuncDeclaration(); + if (thisfd) + { if (!thisfd->isNested() && !thisfd->vthis) + goto Lerr; + } + else { - error(loc, "cannot access frame of function %s", fd->toChars()); - return 1; + ClassDeclaration *thiscd = s->isClassDeclaration(); + if (thiscd) + { if (!thiscd->isNested()) + goto Lerr; + } + else + goto Lerr; } - s = thisfd->toParent(); - thisfd = s->isFuncDeclaration(); + + s = s->toParent(); + assert(s); level++; } return level; + +Lerr: + error(loc, "cannot access frame of function %s", fd->toChars()); + return 1; } void FuncDeclaration::appendExp(Expression *e) diff -uNr dmd-0.125/dmd/src/dmd/html.c dmd-0.126/dmd/src/dmd/html.c --- dmd-0.125/dmd/src/dmd/html.c 2005-04-26 15:23:58.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/html.c 2005-05-25 21:51:30.000000000 +0200 @@ -67,15 +67,18 @@ void Html::error(const char *format, ...) { - printf("%s(%d) : HTML Error: ", sourcename, linnum); + if (!global.gag) + { + printf("%s(%d) : HTML Error: ", sourcename, linnum); - va_list ap; - va_start(ap, format); - vprintf(format, ap); - va_end(ap); + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); - printf("\n"); - fflush(stdout); + printf("\n"); + fflush(stdout); + } global.errors++; } diff -uNr dmd-0.125/dmd/src/dmd/idgen.c dmd-0.126/dmd/src/dmd/idgen.c --- dmd-0.125/dmd/src/dmd/idgen.c 2005-04-11 22:35:08.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/idgen.c 2005-06-02 01:10:00.000000000 +0200 @@ -44,6 +44,7 @@ { "__sizeof", "sizeof" }, { "alignof" }, { "length" }, + { "remove" }, { "ptr" }, { "dollar", "__dollar" }, { "offset" }, diff -uNr dmd-0.125/dmd/src/dmd/init.c dmd-0.126/dmd/src/dmd/init.c --- dmd-0.125/dmd/src/dmd/init.c 2005-04-26 17:27:28.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/init.c 2005-06-01 14:20:08.000000000 +0200 @@ -20,7 +20,7 @@ #include "mtype.h" -/********************************** Initializer ************************************/ +/********************************** Initializer *******************************/ Initializer::Initializer(Loc loc) { @@ -29,8 +29,7 @@ Initializer *Initializer::syntaxCopy() { - assert(0); // BUG: implement - return NULL; + return this; } Initializer *Initializer::semantic(Scope *sc, Type *t) @@ -55,7 +54,42 @@ return a; } -/********************************** StructInitializer ************************************/ +/********************************** VoidInitializer ***************************/ + +VoidInitializer::VoidInitializer(Loc loc) + : Initializer(loc) +{ + type = NULL; +} + + +Initializer *VoidInitializer::syntaxCopy() +{ + return new VoidInitializer(loc); +} + + +Initializer *VoidInitializer::semantic(Scope *sc, Type *t) +{ + type = t; + return this; +} + + +Expression *VoidInitializer::toExpression() +{ + assert(0); + return NULL; +} + + +void VoidInitializer::toCBuffer(OutBuffer *buf) +{ + buf->writestring("void"); +} + + +/********************************** StructInitializer *************************/ StructInitializer::StructInitializer(Loc loc) : Initializer(loc) diff -uNr dmd-0.125/dmd/src/dmd/init.h dmd-0.126/dmd/src/dmd/init.h --- dmd-0.125/dmd/src/dmd/init.h 2005-02-12 01:48:12.000000000 +0100 +++ dmd-0.126/dmd/src/dmd/init.h 2005-06-01 14:20:08.000000000 +0200 @@ -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 @@ -20,6 +20,7 @@ struct Type; struct dt_t; struct AggregateDeclaration; +struct VoidInitializer; struct ExpInitializer; struct Initializer : Object @@ -36,7 +37,23 @@ virtual dt_t *toDt(); - virtual ExpInitializer *isExpInitializer() { return NULL; } + virtual VoidInitializer *isVoidInitializer() { return NULL; } + virtual ExpInitializer *isExpInitializer() { return NULL; } +}; + +struct VoidInitializer : Initializer +{ + Type *type; // type that this will initialize to + + VoidInitializer(Loc loc); + Initializer *syntaxCopy(); + Initializer *semantic(Scope *sc, Type *t); + Expression *toExpression(); + void toCBuffer(OutBuffer *buf); + + dt_t *toDt(); + + virtual VoidInitializer *isVoidInitializer() { return this; } }; struct StructInitializer : Initializer diff -uNr dmd-0.125/dmd/src/dmd/inline.c dmd-0.126/dmd/src/dmd/inline.c --- dmd-0.125/dmd/src/dmd/inline.c 2005-04-05 23:12:40.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/inline.c 2005-05-21 01:39:20.000000000 +0200 @@ -968,7 +968,7 @@ isSynchronized() || isImportedSymbol() || !fbody || - tf->varargs || // no variadic parameter lists + tf->varargs == 1 || // no variadic parameter lists nestedFrameRef || // no nested references to this frame (isVirtual() && !isFinal()) ) diff -uNr dmd-0.125/dmd/src/dmd/lexer.c dmd-0.126/dmd/src/dmd/lexer.c --- dmd-0.125/dmd/src/dmd/lexer.c 2005-05-18 15:17:28.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/lexer.c 2005-05-25 21:53:02.000000000 +0200 @@ -224,42 +224,48 @@ void Lexer::error(const char *format, ...) { - char *p = loc.toChars(); - if (*p) - printf("%s: ", p); - mem.free(p); - - va_list ap; - va_start(ap, format); - vprintf(format, ap); - va_end(ap); + if (!global.gag) + { + char *p = loc.toChars(); + if (*p) + printf("%s: ", p); + mem.free(p); + + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); - printf("\n"); - fflush(stdout); + printf("\n"); + fflush(stdout); + if (global.errors >= 20) // moderate blizzard of cascading messages + fatal(); + } global.errors++; - if (global.errors > 20) // moderate blizzard of cascading messages - fatal(); } void Lexer::error(Loc loc, const char *format, ...) { - char *p = loc.toChars(); - if (*p) - printf("%s: ", p); - mem.free(p); - - va_list ap; - va_start(ap, format); - vprintf(format, ap); - va_end(ap); + if (!global.gag) + { + char *p = loc.toChars(); + if (*p) + printf("%s: ", p); + mem.free(p); + + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); - printf("\n"); - fflush(stdout); + printf("\n"); + fflush(stdout); + if (global.errors >= 20) // moderate blizzard of cascading messages + fatal(); + } global.errors++; - if (global.errors > 20) // moderate blizzard of cascading messages - fatal(); } TOK Lexer::nextToken() @@ -2112,7 +2118,7 @@ { "delegate", TOKdelegate }, { "function", TOKfunction }, - { "is", TOKidentity }, + { "is", TOKis }, { "if", TOKif }, { "else", TOKelse }, { "while", TOKwhile }, @@ -2210,7 +2216,7 @@ Token::tochars[TOKge] = ">="; Token::tochars[TOKequal] = "=="; Token::tochars[TOKnotequal] = "!="; -// Token::tochars[TOKidentity] = "==="; + Token::tochars[TOKidentity] = "==="; Token::tochars[TOKnotidentity] = "!=="; Token::tochars[TOKunord] = "!<>="; diff -uNr dmd-0.125/dmd/src/dmd/lexer.h dmd-0.126/dmd/src/dmd/lexer.h --- dmd-0.125/dmd/src/dmd/lexer.h 2005-05-13 01:17:50.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/lexer.h 2005-06-06 14:47:12.000000000 +0200 @@ -64,14 +64,15 @@ TOKdeclaration, TOKtypeof, TOKpragma, TOKdsymbol, TOKtypeid, TOKuadd, - TOKiftype, + TOKiftype, TOKremove, + TOKnewanonclass, // Operators TOKlt, TOKgt, TOKle, TOKge, TOKequal, TOKnotequal, TOKidentity, TOKnotidentity, - TOKindex, + TOKindex, TOKis, // NCEG floating point compares // !<>= <> <>= !> !>= !< !<= !<> diff -uNr dmd-0.125/dmd/src/dmd/mars.c dmd-0.126/dmd/src/dmd/mars.c --- dmd-0.125/dmd/src/dmd/mars.c 2005-05-19 16:13:46.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/mars.c 2005-05-27 01:16:28.000000000 +0200 @@ -49,7 +49,7 @@ copyright = "Copyright (c) 1999-2005 by Digital Mars"; written = "written by Walter Bright"; - version = "v0.125"; + version = "v0.126"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); @@ -83,20 +83,22 @@ void error(Loc loc, const char *format, ...) { - char *p = loc.toChars(); - - if (*p) - printf("%s: ", p); - mem.free(p); - - va_list ap; - va_start(ap, format); - printf("Error: "); - vprintf(format, ap); - va_end( ap ); - printf("\n"); - fflush(stdout); + if (!global.gag) + { + char *p = loc.toChars(); + if (*p) + printf("%s: ", p); + mem.free(p); + + va_list ap; + va_start(ap, format); + printf("Error: "); + vprintf(format, ap); + va_end( ap ); + printf("\n"); + fflush(stdout); + } global.errors++; } diff -uNr dmd-0.125/dmd/src/dmd/mars.h dmd-0.126/dmd/src/dmd/mars.h --- dmd-0.125/dmd/src/dmd/mars.h 2005-05-11 21:11:56.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/mars.h 2005-05-25 21:40:40.000000000 +0200 @@ -85,6 +85,7 @@ Param params; unsigned errors; // number of errors reported so far + unsigned gag; // !=0 means gag reporting of errors Global(); }; diff -uNr dmd-0.125/dmd/src/dmd/mtype.c dmd-0.126/dmd/src/dmd/mtype.c --- dmd-0.125/dmd/src/dmd/mtype.c 2005-05-18 22:31:16.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/mtype.c 2005-05-25 21:58:10.000000000 +0200 @@ -566,21 +566,22 @@ void Type::error(Loc loc, const char *format, ...) { - char *p = loc.toChars(); - if (*p) - printf("%s: ", p); - mem.free(p); - - va_list ap; - va_start(ap, format); - vprintf(format, ap); - va_end(ap); - - printf("\n"); - fflush(stdout); + if (!global.gag) + { + char *p = loc.toChars(); + if (*p) + printf("%s: ", p); + mem.free(p); + + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + printf("\n"); + fflush(stdout); + } global.errors++; - //fatal(); } Identifier *Type::getTypeInfoIdent(int internal) @@ -2255,7 +2256,7 @@ arg->type->toDecoBuffer(buf); } } - buf->writeByte(varargs ? 'Y' : 'Z'); // mark end of arg list + buf->writeByte('Z' - varargs); // mark end of arg list next->toDecoBuffer(buf); } @@ -2322,7 +2323,7 @@ } if (varargs) { - if (i) + if (i && varargs == 1) buf->writeByte(','); buf->writestring("..."); } @@ -2372,8 +2373,8 @@ } deco = merge()->deco; - if (varargs && linkage != LINKd && !(arguments && arguments->dim)) - error(loc, "variadic functions with non-C linkage must have at least one parameter"); + if (varargs == 1 && linkage != LINKd && !(arguments && arguments->dim)) + error(loc, "variadic functions with non-D linkage must have at least one parameter"); /* Don't return merge(), because arg identifiers and default args * can be different @@ -2383,7 +2384,7 @@ } /******************************** - * Assume 'toargs' are being matched to function 'this' + * 'args' are being matched to function 'this' * Determine match level. * Returns: * 0 no match @@ -2391,52 +2392,92 @@ * 2 exact match */ -int TypeFunction::callMatch(Array *toargs) +int TypeFunction::callMatch(Array *args) { unsigned u; - unsigned nargsf; - unsigned nargst; + unsigned nparams; + unsigned nargs; int match; //printf("TypeFunction::callMatch()\n"); match = 2; // assume exact match - nargsf = arguments ? arguments->dim : 0; - nargst = toargs ? toargs->dim : 0; - if (nargsf == nargst) + nparams = arguments ? arguments->dim : 0; + nargs = args ? args->dim : 0; + if (nparams == nargs) ; - else if (nargst > nargsf) + else if (nargs > nparams) { - if (!varargs) + if (varargs == 0) goto Nomatch; // too many args; no match match = 1; // match ... with a "conversion" match level } - for (u = 0; u < nargsf; u++) + for (u = 0; u < nparams; u++) { int m; - Argument *af; - Expression *ae; + Argument *p; + Expression *arg; // BUG: what about out and inout? - af = (Argument *)arguments->data[u]; - assert(af); - if (u >= nargst) + p = (Argument *)arguments->data[u]; + assert(p); + if (u >= nargs) { - if (af->defaultArg) + if (p->defaultArg) continue; + if (varargs == 2 && u + 1 == nparams) + goto L1; goto Nomatch; // not enough arguments } - ae = (Expression *)toargs->data[u]; - assert(ae); - m = ae->implicitConvTo(af->type); + arg = (Expression *)args->data[u]; + assert(arg); + m = arg->implicitConvTo(p->type); //printf("\tm = %d\n", m); - if (m == 0) - goto Nomatch; // no match for this argument + if (m == 0) // if no match + { + L1: + if (varargs == 2 && u + 1 == nparams) // if last varargs param + { Type *tb = p->type->toBasetype(); + TypeSArray *tsa; + integer_t sz; + + switch (tb->ty) + { + case Tsarray: + tsa = (TypeSArray *)tb; + sz = tsa->dim->toInteger(); + if (sz != nargs - u) + goto Nomatch; + case Tarray: + for (; u < nargs; u++) + { + arg = (Expression *)args->data[u]; + assert(arg); + m = arg->implicitConvTo(tb->next); + if (m == 0) + goto Nomatch; + if (m < match) + match = m; + } + goto Ldone; + + case Tclass: + // Should see if there's a constructor match? + // Or just leave it ambiguous? + goto Ldone; + + default: + goto Nomatch; + } + } + goto Nomatch; + } if (m < match) match = m; // pick worst match } +Ldone: //printf("match = %d\n", match); return match; @@ -4016,7 +4057,7 @@ } if (varargs) { - if (i) + if (i && varargs == 1) buf->writeByte(','); buf->writestring("..."); } diff -uNr dmd-0.125/dmd/src/dmd/mtype.h dmd-0.126/dmd/src/dmd/mtype.h --- dmd-0.125/dmd/src/dmd/mtype.h 2005-04-11 22:36:54.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/mtype.h 2005-05-21 01:36:02.000000000 +0200 @@ -380,7 +380,8 @@ struct TypeFunction : Type { Array *arguments; // Array of Argument's - int varargs; // if variable number of arguments + int varargs; // 1: T t, ...) style for variable number of arguments + // 2: T t ...) style for variable number of arguments enum LINK linkage; // calling convention TypeFunction(Array *arguments, Type *treturn, int varargs, enum LINK linkage); diff -uNr dmd-0.125/dmd/src/dmd/parse.c dmd-0.126/dmd/src/dmd/parse.c --- dmd-0.125/dmd/src/dmd/parse.c 2005-05-20 15:40:32.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/parse.c 2005-06-06 12:14:56.000000000 +0200 @@ -643,6 +643,7 @@ Type *targ; Identifier *ident = NULL; Type *tspec = NULL; + enum TOK tok = TOKreserved; Loc loc = this->loc; nextToken(); @@ -651,22 +652,24 @@ nextToken(); targ = parseBasicType(); targ = parseDeclarator(targ, &ident); - if (token.value == TOKcolon) + if (token.value == TOKcolon || token.value == TOKequal) { + tok = token.value; nextToken(); tspec = parseBasicType(); tspec = parseDeclarator(tspec, NULL); } check(TOKrparen); - - if (!ident && !tspec) - error("expected either Identifier or TypeSpecialization or both"); } else { error("(type identifier : specialization) expected following iftype"); return NULL; } - Condition *condition = new IftypeCondition(loc, targ, ident, tspec); + Condition *condition = new IftypeCondition(loc, targ, ident, tok, tspec); + + if (!global.params.useDeprecated) + error("iftype(condition) is deprecated, use static if (is(condition))"); + return condition; } @@ -885,6 +888,7 @@ L1: tb = parseBasicType(); at = parseDeclarator(tb, &ai); + ae = NULL; if (token.value == TOKassign) // = defaultArg { nextToken(); ae = parseAssignExp(); @@ -894,7 +898,19 @@ { if (hasdefault) error("default argument expected for %s", ai ? ai->toChars() : at->toChars()); - ae = NULL; + } + if (token.value == TOKdotdotdot) + { /* This is: + * at ai ... + */ + + if (inout != In) + error("variadic argument cannot be out or inout"); + varargs = 2; + a = new Argument(inout, at, ai, ae); + arguments->push(a); + nextToken(); + break; } a = new Argument(inout, at, ai, ae); arguments->push(a); @@ -1010,48 +1026,16 @@ { case TOKclass: case TOKinterface: { - Array *baseclasses = NULL; - BaseClass *b; - if (!id) error("anonymous classes not allowed"); // Collect base class(es) - b = NULL; + Array *baseclasses = NULL; if (token.value == TOKcolon) - { enum PROT protection = PROTpublic; + { + nextToken(); + baseclasses = parseBaseClasses(); - baseclasses = new Array(); - while (1) - { - nextToken(); - switch (token.value) - { - case TOKidentifier: - case TOKinstance: - break; - case TOKprivate: - protection = PROTprivate; - continue; - case TOKpackage: - protection = PROTpackage; - continue; - case TOKprotected: - protection = PROTprotected; - continue; - case TOKpublic: - protection = PROTpublic; - continue; - default: - error("base classes expected following ':'"); - return NULL; - } - b = new BaseClass(parseBasicType(), protection); - baseclasses->push(b); - if (token.value != TOKcomma) - break; - protection = PROTpublic; - } if (token.value != TOKlcurly) error("members expected"); } @@ -1121,6 +1105,46 @@ return a; } +/******************************************* + */ + +Array *Parser::parseBaseClasses() +{ + enum PROT protection = PROTpublic; + Array *baseclasses = new Array(); + + for (; 1; nextToken()) + { + switch (token.value) + { + case TOKidentifier: + case TOKinstance: + break; + case TOKprivate: + protection = PROTprivate; + continue; + case TOKpackage: + protection = PROTpackage; + continue; + case TOKprotected: + protection = PROTprotected; + continue; + case TOKpublic: + protection = PROTpublic; + continue; + default: + error("base classes expected"); + return NULL; + } + BaseClass *b = new BaseClass(parseBasicType(), protection); + baseclasses->push(b); + if (token.value != TOKcomma) + break; + protection = PROTpublic; + } + return baseclasses; +} + /************************************** * Parse a TemplateDeclaration. */ @@ -1948,6 +1972,16 @@ } a = new Array(); + + if (token.value == TOKclass) + { AggregateDeclaration *s; + + s = (AggregateDeclaration *)parseAggregate(); + s->storage_class |= storage_class; + a->push(s); + return a; + } + ts = parseBasicType(); ts = parseBasicType2(ts); tfirst = NULL; @@ -2251,6 +2285,10 @@ } return ia; + case TOKvoid: + nextToken(); + return new VoidInitializer(loc); + default: e = parseAssignExp(); ie = new ExpInitializer(loc, e); @@ -2336,6 +2374,7 @@ case TOKdelegate: case TOKfunction: case TOKtypeid: + case TOKis: Lexp: { Expression *exp; @@ -3488,7 +3527,7 @@ case TOKidentifier: id = token.ident; nextToken(); - if (token.value == TOKnot) + if (token.value == TOKnot && peek(&token)->value == TOKlparen) { // identifier!(template-argument-list) TemplateInstance *tempinst; @@ -3668,6 +3707,53 @@ break; } + case TOKis: + { Type *targ; + Identifier *ident = NULL; + Type *tspec = NULL; + enum TOK tok = TOKreserved; + enum TOK tok2 = TOKreserved; + Loc loc = this->loc; + + nextToken(); + if (token.value == TOKlparen) + { + nextToken(); + targ = parseBasicType(); + targ = parseDeclarator(targ, &ident); + if (token.value == TOKcolon || token.value == TOKequal) + { + tok = token.value; + nextToken(); + if (tok == TOKequal && + (token.value == TOKtypedef || + token.value == TOKstruct || + token.value == TOKunion || + token.value == TOKclass || + token.value == TOKenum || + token.value == TOKinterface || + token.value == TOKfunction || + token.value == TOKdelegate)) + { + tok2 = token.value; + nextToken(); + } + else + { + tspec = parseBasicType(); + tspec = parseDeclarator(tspec, NULL); + } + } + check(TOKrparen); + } + else + { error("(type identifier : specialization) expected following is"); + return NULL; + } + e = new IftypeExp(loc, targ, ident, tok, tspec, tok2); + break; + } + case TOKassert: nextToken(); check(TOKlparen, "assert"); @@ -3749,7 +3835,7 @@ { Identifier *id = token.ident; nextToken(); - if (token.value == TOKnot) + if (token.value == TOKnot && peek(&token)->value == TOKlparen) { // identifier!(template-argument-list) TemplateInstance *tempinst; @@ -3904,85 +3990,9 @@ break; case TOKnew: - { Type *t; - Array *newargs; - Array *arguments = NULL; - - nextToken(); - newargs = NULL; - if (token.value == TOKlparen) - { - newargs = parseArguments(); - } - -#if LTORARRAYDECL - t = parseBasicType(); - t = parseBasicType2(t); - if (t->ty == Taarray) - { - Type *index = ((TypeAArray *)t)->index; - - if (index->ty == Tident) - { - TypeIdentifier *ti = (TypeIdentifier *)index; - int i; - Expression *e; - Identifier *id = ti->ident; - - e = new IdentifierExp(loc, id); - for (i = 0; i < ti->idents.dim; i++) - { - id = (Identifier *)ti->idents.data[i]; - e = new DotIdExp(loc, e, id); - } - - arguments = new Array(); - arguments->push(e); - t = new TypeDArray(t->next); - } - else - { - error("need size of rightmost array, not type %s", index->toChars()); - return new NullExp(loc); - } - } - else if (t->ty == Tsarray) - { - TypeSArray *tsa = (TypeSArray *)t; - Expression *e = tsa->dim; - - arguments = new Array(); - arguments->push(e); - t = new TypeDArray(t->next); - } - else if (token.value == TOKlparen) - { - arguments = parseArguments(); - } -#else - t = parseBasicType(); - while (token.value == TOKmul) - { t = new TypePointer(t); - nextToken(); - } - if (token.value == TOKlbracket) - { - Expression *e; - - nextToken(); - e = parseAssignExp(); - arguments = new Array(); - arguments->push(e); - check(TOKrbracket); - t = parseDeclarator(t, NULL); - t = new TypeDArray(t); - } - else if (token.value == TOKlparen) - arguments = parseArguments(); -#endif - e = new NewExp(loc, newargs, t, arguments); + e = parseNewExp(); break; - } + #if DCASTSYNTAX case TOKcast: // cast(type) expression { Type *t; @@ -4216,6 +4226,7 @@ Expression *Parser::parseEqualExp() { Expression *e; Expression *e2; + Token *t; Loc loc = this->loc; e = parseRelExp(); @@ -4232,7 +4243,29 @@ continue; case TOKidentity: + if (!global.params.useDeprecated) + error("'===' is deprecated, use 'is' instead"); + goto L1; + case TOKnotidentity: + if (!global.params.useDeprecated) + error("'!==' is deprecated, use '!is' instead"); + goto L1; + + case TOKis: + value = TOKidentity; + goto L1; + + case TOKnot: + // Attempt to identify '!is' + t = peek(&token); + if (t->value != TOKis) + break; + nextToken(); + value = TOKnotidentity; + goto L1; + + L1: nextToken(); e2 = parseRelExp(); e = new IdentityExp(value, loc, e, e2); @@ -4425,5 +4458,121 @@ return arguments; } +/******************************************* + */ + +Expression *Parser::parseNewExp() +{ Type *t; + Array *newargs; + Array *arguments = NULL; + Expression *e; + Loc loc = this->loc; + + nextToken(); + newargs = NULL; + if (token.value == TOKlparen) + { + newargs = parseArguments(); + } + + // An anonymous nested class starts with "class" + if (token.value == TOKclass) + { + nextToken(); + if (token.value == TOKlparen) + arguments = parseArguments(); + + Array *baseclasses = parseBaseClasses(); + Identifier *id = NULL; + ClassDeclaration *cd = new ClassDeclaration(loc, id, baseclasses); + + if (token.value != TOKlcurly) + { error("{ members } expected for anonymous class"); + cd->members = NULL; + } + else + { + nextToken(); + Array *decl = parseDeclDefs(0); + if (token.value != TOKrcurly) + error("class member expected"); + nextToken(); + cd->members = decl; + } + + e = new NewAnonClassExp(loc, newargs, cd, arguments); + + return e; + } + +#if LTORARRAYDECL + t = parseBasicType(); + t = parseBasicType2(t); + if (t->ty == Taarray) + { + Type *index = ((TypeAArray *)t)->index; + + if (index->ty == Tident) + { + TypeIdentifier *ti = (TypeIdentifier *)index; + int i; + Expression *e; + Identifier *id = ti->ident; + + e = new IdentifierExp(loc, id); + for (i = 0; i < ti->idents.dim; i++) + { + id = (Identifier *)ti->idents.data[i]; + e = new DotIdExp(loc, e, id); + } + + arguments = new Array(); + arguments->push(e); + t = new TypeDArray(t->next); + } + else + { + error("need size of rightmost array, not type %s", index->toChars()); + return new NullExp(loc); + } + } + else if (t->ty == Tsarray) + { + TypeSArray *tsa = (TypeSArray *)t; + Expression *e = tsa->dim; + + arguments = new Array(); + arguments->push(e); + t = new TypeDArray(t->next); + } + else if (token.value == TOKlparen) + { + arguments = parseArguments(); + } +#else + t = parseBasicType(); + while (token.value == TOKmul) + { t = new TypePointer(t); + nextToken(); + } + if (token.value == TOKlbracket) + { + Expression *e; + + nextToken(); + e = parseAssignExp(); + arguments = new Array(); + arguments->push(e); + check(TOKrbracket); + t = parseDeclarator(t, NULL); + t = new TypeDArray(t); + } + else if (token.value == TOKlparen) + arguments = parseArguments(); +#endif + e = new NewExp(loc, newargs, t, arguments); + return e; +} + /********************************* ***************************/ diff -uNr dmd-0.125/dmd/src/dmd/parse.h dmd-0.126/dmd/src/dmd/parse.h --- dmd-0.125/dmd/src/dmd/parse.h 2005-05-15 02:13:12.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/parse.h 2005-06-06 12:14:54.000000000 +0200 @@ -73,6 +73,7 @@ Array *parseParameters(int *pvarargs); EnumDeclaration *parseEnum(); Dsymbol *parseAggregate(); + Array *parseBaseClasses(); Import *parseImport(Array *decldefs); Type *parseBasicType(); Type *parseBasicType2(Type *t); @@ -109,6 +110,8 @@ Expression *parseAssignExp(); Array *parseArguments(); + + Expression *parseNewExp(); }; #endif /* DMD_PARSE_H */ diff -uNr dmd-0.125/dmd/src/dmd/scope.c dmd-0.126/dmd/src/dmd/scope.c --- dmd-0.125/dmd/src/dmd/scope.c 2005-05-12 18:52:16.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/scope.c 2005-05-26 17:18:50.000000000 +0200 @@ -43,6 +43,7 @@ this->module = NULL; this->scopesym = NULL; + this->sd = NULL; this->enclosing = NULL; this->parent = NULL; this->sw = NULL; @@ -72,6 +73,7 @@ this->func = enclosing->func; this->parent = enclosing->parent; this->scopesym = NULL; + this->sd = NULL; this->sw = enclosing->sw; this->tf = enclosing->tf; this->sbreak = enclosing->sbreak; diff -uNr dmd-0.125/dmd/src/dmd/scope.h dmd-0.126/dmd/src/dmd/scope.h --- dmd-0.125/dmd/src/dmd/scope.h 2005-03-13 16:20:48.000000000 +0100 +++ dmd-0.126/dmd/src/dmd/scope.h 2005-05-26 17:22:08.000000000 +0200 @@ -37,6 +37,8 @@ Module *module; // Root module ScopeDsymbol *scopesym; // current symbol + ScopeDsymbol *sd; // if in static if, and declaring new symbols, + // sd gets the addMember() FuncDeclaration *func; // function we are in Dsymbol *parent; // parent to use LabelStatement *slabel; // enclosing labelled statement @@ -65,6 +67,7 @@ unsigned stc; // storage class unsigned flags; #define SCOPEctor 1 // constructor type +#define SCOPEstaticif 2 // inside static if AnonymousAggregateDeclaration *anonAgg; // for temporary analysis diff -uNr dmd-0.125/dmd/src/dmd/statement.c dmd-0.126/dmd/src/dmd/statement.c --- dmd-0.125/dmd/src/dmd/statement.c 2005-05-15 11:49:52.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/statement.c 2005-05-25 21:54:12.000000000 +0200 @@ -81,21 +81,22 @@ void Statement::error(const char *format, ...) { - char *p = loc.toChars(); - if (*p) - printf("%s: ", p); - mem.free(p); - - va_list ap; - va_start(ap, format); - vprintf(format, ap); - va_end(ap); - - printf("\n"); - fflush(stdout); + if (!global.gag) + { + char *p = loc.toChars(); + if (*p) + printf("%s: ", p); + mem.free(p); + + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + printf("\n"); + fflush(stdout); + } global.errors++; - fatal(); } int Statement::hasBreak() @@ -1661,6 +1662,10 @@ if (tbret->ty != Tvoid) exp = exp->implicitCastTo(tret); } + exp = exp->optimize(WANTvalue); + //exp->dump(0); + //exp->print(); + exp->checkEscape(); } else if (tbret->ty != Tvoid) // if non-void return error("return expression expected"); diff -uNr dmd-0.125/dmd/src/dmd/struct.c dmd-0.126/dmd/src/dmd/struct.c --- dmd-0.125/dmd/src/dmd/struct.c 2005-05-12 18:53:12.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/struct.c 2005-06-03 01:22:34.000000000 +0200 @@ -26,6 +26,7 @@ { this->loc = loc; + storage_class = 0; type = NULL; handle = NULL; structsize = 0; // size of struct diff -uNr dmd-0.125/dmd/src/dmd/tocsym.c dmd-0.126/dmd/src/dmd/tocsym.c --- dmd-0.125/dmd/src/dmd/tocsym.c 2005-05-18 22:35:18.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/tocsym.c 2005-05-31 18:55:54.000000000 +0200 @@ -144,7 +144,7 @@ { Symbol *s; TYPE *t; const char *id; - mangle_t m; + mangle_t m = 0; if (isDataseg()) id = mangle(); diff -uNr dmd-0.125/dmd/src/dmd/todt.c dmd-0.126/dmd/src/dmd/todt.c --- dmd-0.125/dmd/src/dmd/todt.c 2005-05-19 01:08:20.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/todt.c 2005-06-01 14:21:16.000000000 +0200 @@ -50,6 +50,17 @@ } +dt_t *VoidInitializer::toDt() +{ /* Void initializers are set to 0, just because we need something + * to set them to in the static data segment. + */ + dt_t *dt = NULL; + + dtnzeros(&dt, type->size()); + return dt; +} + + dt_t *StructInitializer::toDt() { Array dts; diff -uNr dmd-0.125/dmd/src/dmd/toobj.c dmd-0.126/dmd/src/dmd/toobj.c --- dmd-0.125/dmd/src/dmd/toobj.c 2005-05-18 22:30:38.000000000 +0200 +++ dmd-0.126/dmd/src/dmd/toobj.c 2005-06-02 13:52:14.000000000 +0200 @@ -859,16 +859,16 @@ } } } + else if (storage_class & STCextern) + { + s->Sclass = SCextern; + s->Sfl = FLextern; + s->Sdt = NULL; + // BUG: if isExport(), shouldn't we make it dllimport? + return; + } else { - if (storage_class & STCextern) - { - s->Sclass = SCextern; - s->Sfl = FLextern; - s->Sdt = NULL; - // BUG: if isExport(), shouldn't we make it dllimport? - return; - } type->toDt(&s->Sdt); } dt_optimize(s->Sdt); diff -uNr dmd-0.125/dmd/src/phobos/internal/aaA.d dmd-0.126/dmd/src/phobos/internal/aaA.d --- dmd-0.125/dmd/src/phobos/internal/aaA.d 2005-05-20 15:41:14.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/internal/aaA.d 2005-06-07 21:54:14.000000000 +0200 @@ -233,6 +233,47 @@ /************************************************* + * Get pointer to value in associative array indexed by key. + * Returns null if it is not already there. + */ + +void *_aaGetRvalue(aaA*[] aa, TypeInfo keyti, int valuesize, ...) + { + void *pkey = cast(void *)(&valuesize + 1); + uint key_hash; + uint i; + aaA *e; + aaA **pe; + int keysize = keyti.tsize(); + + if (aa.length) + { + key_hash = keyti.getHash(pkey); + //printf("hash = %d\n", key_hash); + i = (key_hash % (aa.length - 1)) + 1; + pe = &aa[i]; + while ((e = *pe) != null) + { int c; + + c = key_hash - e.hash; + if (c == 0) + { + c = keyti.compare(pkey, e + 1); + if (c == 0) + return cast(void *)(e + 1) + keysize; + } + + if (c < 0) + pe = &e.left; + else + pe = &e.right; + } + } + return null; // not found, caller will throw exception + } + + +/************************************************* * Determine if key is in aa. * Returns: * null not in aa diff -uNr dmd-0.125/dmd/src/phobos/internal/gc/gclinux.d dmd-0.126/dmd/src/phobos/internal/gc/gclinux.d --- dmd-0.125/dmd/src/phobos/internal/gc/gclinux.d 2005-05-20 15:41:14.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/internal/gc/gclinux.d 2005-06-07 21:54:16.000000000 +0200 @@ -77,7 +77,22 @@ void *os_query_stackBottom() { - return __libc_stack_end; + version (none) + { // See discussion: http://autopackage.org/forums/viewtopic.php?t=22 + static void** libc_stack_end; + + if (libc_stack_end == libc_stack_end.init) + { + void* handle = dlopen(null, RTLD_NOW); + libc_stack_end = cast(void **)dlsym(handle, "__libc_stack_end"); + dlclose(handle); + } + return *libc_stack_end; + } + else + { // This doesn't resolve on all versions of Linux + return __libc_stack_end; + } } diff -uNr dmd-0.125/dmd/src/phobos/internal/invariant.d dmd-0.126/dmd/src/phobos/internal/invariant.d --- dmd-0.125/dmd/src/phobos/internal/invariant.d 2005-05-20 15:41:14.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/internal/invariant.d 2005-06-07 21:54:14.000000000 +0200 @@ -11,7 +11,7 @@ //printf("__d_invariant(%p)\n", o); // BUG: needs to be filename/line of caller, not library routine - assert(o !== null); // just do null check, not invariant check + assert(o !is null); // just do null check, not invariant check c = o.classinfo; do diff -uNr dmd-0.125/dmd/src/phobos/internal/trace.d dmd-0.126/dmd/src/phobos/internal/trace.d --- dmd-0.125/dmd/src/phobos/internal/trace.d 2005-05-20 15:41:14.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/internal/trace.d 2005-06-07 21:54:14.000000000 +0200 @@ -354,7 +354,7 @@ fprintf(fplog,"%7d\t%3lld.%07lld\t%3lld.%07lld\t%3lld.%07lld\t%.*s\n", calls,tl,tr,fl,fr,pl,pr,id); } - if (id !== s.Sident) + if (id !is s.Sident) free(id); } } diff -uNr dmd-0.125/dmd/src/phobos/linux.mak dmd-0.126/dmd/src/phobos/linux.mak --- dmd-0.125/dmd/src/phobos/linux.mak 2005-05-20 15:41:12.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/linux.mak 2005-06-07 21:54:12.000000000 +0200 @@ -51,7 +51,7 @@ compiler.o system.o moduleinit.o md5.o base64.o \ cast.o path.o string.o memset.o math.o mmfile.o \ outbuffer.o ctype.o regexp.o random.o linux.o linuxsocket.o \ - stream.o switcherr.o array.o gc.o \ + stream.o cstream.o switcherr.o array.o gc.o \ qsort.o thread.o obj.o utf.o uri.o \ crc32.o conv.o arraycast.o errno.o alloca.o cmath2.o \ process.o syserror.o \ @@ -99,7 +99,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/boxer.d std/cstream.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 @@ -481,6 +481,9 @@ conv.o : std/conv.d $(DMD) -c $(DFLAGS) std/conv.d +cstream.o : std/cstream.d + $(DMD) -c $(DFLAGS) std/cstream.d + ctype.o : std/ctype.d $(DMD) -c $(DFLAGS) std/ctype.d @@ -551,7 +554,7 @@ $(DMD) -c $(DFLAGS) std/stdio.d stream.o : std/stream.d - $(DMD) -c $(DFLAGS) std/stream.d + $(DMD) -c $(DFLAGS) -d std/stream.d string.o : std/string.d $(DMD) -c $(DFLAGS) std/string.d diff -uNr dmd-0.125/dmd/src/phobos/std/base64.d dmd-0.126/dmd/src/phobos/std/base64.d --- dmd-0.125/dmd/src/phobos/std/base64.d 2005-05-20 15:41:14.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/std/base64.d 2005-06-07 21:54:12.000000000 +0200 @@ -75,7 +75,8 @@ sp = &str[0]; for(stri = 0; stri != strmax; stri++) { - x = (*sp++ << 16) | (*sp++ << 8) | (*sp++); + x = (sp[0] << 16) | (sp[1] << 8) | (sp[2]); + sp+= 3; *bp++ = array[(x & 0b11111100_00000000_00000000) >> 18]; *bp++ = array[(x & 0b00000011_11110000_00000000) >> 12]; *bp++ = array[(x & 0b00000000_00001111_11000000) >> 6]; @@ -85,7 +86,8 @@ switch(strleft) { case 2: - x = (*sp++ << 16) | (*sp++ << 8); + x = (sp[0] << 16) | (sp[1] << 8); + sp += 2; *bp++ = array[(x & 0b11111100_00000000_00000000) >> 18]; *bp++ = array[(x & 0b00000011_11110000_00000000) >> 12]; *bp++ = array[(x & 0b00000000_00001111_11000000) >> 6]; @@ -180,8 +182,9 @@ bp = &buf[0]; for(estri = 0; estri != estrmax; estri++) { - x = arrayIndex(*sp++) << 18 | arrayIndex(*sp++) << 12; - + x = arrayIndex(sp[0]) << 18 | arrayIndex(sp[1]) << 12; + sp += 2; + ch = *sp++; if(ch == '=') { diff -uNr dmd-0.125/dmd/src/phobos/std/boxer.d dmd-0.126/dmd/src/phobos/std/boxer.d --- dmd-0.125/dmd/src/phobos/std/boxer.d 2005-05-20 15:41:14.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/std/boxer.d 2005-06-07 21:54:14.000000000 +0200 @@ -136,11 +136,11 @@ TypeInfo_Class ca = cast(TypeInfo_Class) type, cb = cast(TypeInfo_Class) test; - if (ca !== null && cb !== null) + if (ca !is null && cb !is null) { ClassInfo ia = (*cast(Object *) data).classinfo, ib = cb.info; - for ( ; ia !== null; ia = ia.base) + for ( ; ia !is null; ia = ia.base) if (ia is ib) return true; return false; @@ -320,7 +320,7 @@ Box box(TypeInfo type, void* data) in { - assert(type !== null); + assert(type !is null); } body { @@ -407,7 +407,7 @@ { T unboxCastReal(Box value) { - assert (value.type !== null); + assert (value.type !is null); if (value.type is typeid(float)) return cast(T) *cast(float*) value.data; @@ -424,7 +424,7 @@ { T unboxCastInteger(Box value) { - assert (value.type !== null); + assert (value.type !is null); if (value.type is typeid(int)) return cast(T) *cast(int*) value.data; @@ -453,7 +453,7 @@ { T unboxCastComplex(Box value) { - assert (value.type !== null); + assert (value.type !is null); if (value.type is typeid(cfloat)) return cast(T) *cast(cfloat*) value.data; @@ -476,7 +476,7 @@ { T unboxCastImaginary(Box value) { - assert (value.type !== null); + assert (value.type !is null); if (value.type is typeid(ifloat)) return cast(T) *cast(ifloat*) value.data; @@ -499,7 +499,7 @@ { T unbox(Box value) { - assert (value.type !== null); + assert (value.type !is null); if (typeid(T) is value.type) return *cast(T*) value.data; @@ -529,7 +529,7 @@ { T unbox(Box value) { - assert (value.type !== null); + assert (value.type !is null); if (typeid(T) == value.type || cast(TypeInfo_Class) value.type) { @@ -553,7 +553,7 @@ { T[] unbox(Box value) { - assert (value.type !== null); + assert (value.type !is null); if (typeid(T[]) is value.type) return *cast(T[]*) value.data; @@ -567,7 +567,7 @@ { T* unbox(Box value) { - assert (value.type !== null); + assert (value.type !is null); if (typeid(T*) is value.type) return *cast(T**) value.data; @@ -584,7 +584,7 @@ { T unbox(Box value) { - assert (value.type !== null); + assert (value.type !is null); if (cast(TypeInfo_Pointer) value.type) return *cast(void**) value.data; @@ -689,7 +689,7 @@ assert(array.length == 3); assert(unboxTest!(int)(array[0]) == 16); assert(unboxTest!(char[])(array[1]) == "foobar"); - assert(unboxTest!(Object)(array[2]) !== null); + assert(unboxTest!(Object)(array[2]) !is null); /* Convert the box array back into arguments. */ TypeInfo[] array_types; @@ -724,7 +724,7 @@ assert (box(1) == box(true)); /* Assert that unboxing to an object works properly. */ - assert (unboxTest!(B)(box(cast(A)new B)) !== null); + assert (unboxTest!(B)(box(cast(A)new B)) !is null); /* Assert that illegal object casting fails properly. */ assert (fails(delegate void() { unboxTest!(B)(box(new A)); })); diff -uNr dmd-0.125/dmd/src/phobos/std/c/linux/linux.d dmd-0.126/dmd/src/phobos/std/c/linux/linux.d --- dmd-0.125/dmd/src/phobos/std/c/linux/linux.d 2005-05-20 15:41:14.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/std/c/linux/linux.d 2005-06-07 21:54:16.000000000 +0200 @@ -323,3 +323,17 @@ } } +extern (C) +{ + /* From + * See http://www.opengroup.org/onlinepubs/007908799/xsh/dlsym.html + */ + + const int RTLD_NOW = 0x00002; // Correct for Red Hat 8 + + void* dlopen(char* file, int mode); + int dlclose(void* handle); + void* dlsym(void* handle, char* name); + char* dlerror(); +} + diff -uNr dmd-0.125/dmd/src/phobos/std/cstream.d dmd-0.126/dmd/src/phobos/std/cstream.d --- dmd-0.125/dmd/src/phobos/std/cstream.d 1970-01-01 01:00:00.000000000 +0100 +++ dmd-0.126/dmd/src/phobos/std/cstream.d 2005-06-07 21:54:14.000000000 +0200 @@ -0,0 +1,147 @@ +// Written by Ben Hinkle and put in the public domain. + +import std.stream; +import std.c.stdio; + +// wraps a FILE* in a stream class +class CFile : Stream { + FILE* cfile; + + // Construct a CFile from the given FILE* with mode and optional seekable state + this(FILE* cfile, FileMode mode, bool seekable = false) { + super(); + this.file = cfile; + readable = cast(bit)(mode & FileMode.In); + writeable = cast(bit)(mode & FileMode.Out); + this.seekable = seekable; + } + + ~this() { close(); } + + FILE* file() { return cfile; } + void file(FILE* cfile) { + this.cfile = cfile; + isopen = true; + } + + override void flush() { fflush(cfile); } + override void close() { + if (isopen) + fclose(cfile); + isopen = readable = writeable = seekable = false; + } + override bool eof() { + return cast(bool)(readEOF || feof(cfile)); + } + override char getc() { + return cast(char)fgetc(cfile); + } + override char ungetc(char c) { + return cast(char)std.c.stdio.ungetc(c,cfile); + } + override size_t readBlock(void* buffer, size_t size) { + size_t n = fread(buffer,1,size,cfile); + readEOF = cast(bit)(n == 0); + return n; + } + override size_t writeBlock(void* buffer, size_t size) { + return fwrite(buffer,1,size,cfile); + } + override ulong seek(long offset, SeekPos rel) { + readEOF = false; + if (fseek(cfile,cast(int)offset,rel) != 0) + throw new SeekException("unable to move file pointer"); + return ftell(cfile); + } + override void writeLine(char[] s) { + writeString(s); + writeString("\n"); + } + override void writeLineW(wchar[] s) { + writeStringW(s); + writeStringW("\n"); + } + // run a few tests + unittest { + FILE* f = fopen("stream.txt","w"); + assert(f !is null); + CFile file = new CFile(f,FileMode.Out); + int i = 666; + // should be ok to write + assert(file.writeable); + file.writeLine("Testing stream.d:"); + file.writeString("Hello, world!"); + file.write(i); + // string#1 + string#2 + int should give exacly that + version (Win32) + assert(file.position() == 19 + 13 + 4); + version (linux) + assert(file.position() == 18 + 13 + 4); + file.close(); + // no operations are allowed when file is closed + assert(!file.readable && !file.writeable && !file.seekable); + f = fopen("stream.txt","r"); + file = new CFile(f,FileMode.In,true); + // should be ok to read + assert(file.readable); + char[] line = file.readLine(); + char[] exp = "Testing stream.d:"; + assert(line[0] == 'T'); + assert(line.length == exp.length); + assert(!std.string.cmp(line, "Testing stream.d:")); + // jump over "Hello, " + file.seek(7, SeekPos.Current); + version (Win32) + assert(file.position() == 19 + 7); + version (linux) + assert(file.position() == 18 + 7); + assert(!std.string.cmp(file.readString(6), "world!")); + i = 0; file.read(i); + assert(i == 666); + // string#1 + string#2 + int should give exacly that + version (Win32) + assert(file.position() == 19 + 13 + 4); + version (linux) + assert(file.position() == 18 + 13 + 4); + // we must be at the end of file + file.close(); + f = fopen("stream.txt","w+"); + file = new CFile(f,FileMode.In|FileMode.Out,true); + file.writeLine("Testing stream.d:"); + file.writeLine("Another line"); + file.writeLine(""); + file.writeLine("That was blank"); + file.position = 0; + char[][] lines; + foreach(char[] line; file) { + lines ~= line.dup; + } + assert( lines.length == 5 ); + assert( lines[0] == "Testing stream.d:"); + assert( lines[1] == "Another line"); + assert( lines[2] == ""); + assert( lines[3] == "That was blank"); + file.position = 0; + lines = new char[][5]; + foreach(ulong n, char[] line; file) { + lines[n-1] = line.dup; + } + assert( lines[0] == "Testing stream.d:"); + assert( lines[1] == "Another line"); + assert( lines[2] == ""); + assert( lines[3] == "That was blank"); + file.close(); + remove("stream.txt"); + } +} + +// standard IO devices +CFile din, dout, derr; + +static this() { + // open standard I/O devices + din = new CFile(std.c.stdio.stdin,FileMode.In); + dout = new CFile(std.c.stdio.stdout,FileMode.Out); + derr = new CFile(std.c.stdio.stderr,FileMode.Out); +} + diff -uNr dmd-0.125/dmd/src/phobos/std/loader.d dmd-0.126/dmd/src/phobos/std/loader.d --- dmd-0.125/dmd/src/phobos/std/loader.d 2005-05-20 15:41:14.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/std/loader.d 2005-06-07 21:54:12.000000000 +0200 @@ -210,7 +210,7 @@ private HXModule ExeModule_Load_(in char[] moduleName) in { - assert(null !== moduleName); + assert(null !is moduleName); } body { @@ -227,7 +227,7 @@ private HXModule ExeModule_AddRef_(in HXModule hModule) in { - assert(null !== hModule); + assert(null !is hModule); } body { @@ -237,7 +237,7 @@ private void ExeModule_Release_(inout HXModule hModule) in { - assert(null !== hModule); + assert(null !is hModule); } body { @@ -251,7 +251,7 @@ private void *ExeModule_GetSymbol_(inout HXModule hModule, in char[] symbolName) in { - assert(null !== hModule); + assert(null !is hModule); } body { @@ -332,13 +332,13 @@ private HXModule ExeModule_Load_(in char[] moduleName) in { - assert(null !== moduleName); + assert(null !is moduleName); } body { ExeModuleInfo mi = s_modules[moduleName]; - if(null !== mi) + if(null !is mi) { return (++mi.m_cRefs, cast(HXModule)mi); } @@ -366,21 +366,21 @@ private HXModule ExeModule_AddRef_(in HXModule hModule) in { - assert(null !== hModule); + assert(null !is hModule); ExeModuleInfo mi = cast(ExeModuleInfo)hModule; assert(0 < mi.m_cRefs); - assert(null !== mi.m_hmod); - assert(null !== mi.m_name); - assert(null !== s_modules[mi.m_name]); + assert(null !is mi.m_hmod); + assert(null !is mi.m_name); + assert(null !is s_modules[mi.m_name]); assert(mi is s_modules[mi.m_name]); } body { ExeModuleInfo mi = cast(ExeModuleInfo)hModule; - if(null !== mi) + if(null !is mi) { return (++mi.m_cRefs, hModule); } @@ -393,14 +393,14 @@ private void ExeModule_Release_(inout HXModule hModule) in { - assert(null !== hModule); + assert(null !is hModule); ExeModuleInfo mi = cast(ExeModuleInfo)hModule; assert(0 < mi.m_cRefs); - assert(null !== mi.m_hmod); - assert(null !== mi.m_name); - assert(null !== s_modules[mi.m_name]); + assert(null !is mi.m_hmod); + assert(null !is mi.m_name); + assert(null !is s_modules[mi.m_name]); assert(mi is s_modules[mi.m_name]); } body @@ -425,14 +425,14 @@ private void *ExeModule_GetSymbol_(inout HXModule hModule, in char[] symbolName) in { - assert(null !== hModule); + assert(null !is hModule); ExeModuleInfo mi = cast(ExeModuleInfo)hModule; assert(0 < mi.m_cRefs); - assert(null !== mi.m_hmod); - assert(null !== mi.m_name); - assert(null !== s_modules[mi.m_name]); + assert(null !is mi.m_hmod); + assert(null !is mi.m_name); + assert(null !is s_modules[mi.m_name]); assert(mi is s_modules[mi.m_name]); } body @@ -456,14 +456,14 @@ private char[] ExeModule_GetPath_(HXModule hModule) in { - assert(null !== hModule); + assert(null !is hModule); ExeModuleInfo mi = cast(ExeModuleInfo)hModule; assert(0 < mi.m_cRefs); - assert(null !== mi.m_hmod); - assert(null !== mi.m_name); - assert(null !== s_modules[mi.m_name]); + assert(null !is mi.m_hmod); + assert(null !is mi.m_name); + assert(null !is s_modules[mi.m_name]); assert(mi is s_modules[mi.m_name]); } body @@ -509,7 +509,7 @@ this(in HXModule hModule, boolean bTakeOwnership) in { - assert(null !== hModule); + assert(null !is hModule); } body { @@ -538,7 +538,7 @@ this(char[] moduleName) in { - assert(null !== moduleName); + assert(null !is moduleName); } body { @@ -574,7 +574,7 @@ /// calls do not result in an error, and are simply ignored. void close() { - if(null !== m_hModule) + if(null !is m_hModule) { version (Windows) { diff -uNr dmd-0.125/dmd/src/phobos/std/math.d dmd-0.126/dmd/src/phobos/std/math.d --- dmd-0.125/dmd/src/phobos/std/math.d 2005-05-20 15:41:14.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/std/math.d 2005-06-07 21:54:12.000000000 +0200 @@ -334,9 +334,10 @@ jp SC17 ; fstp ST(1) ; // remove pi from stack jmp SC18 ; - } trigerr: + fstp ST(0) ; // dump theta + } return real.nan; Lret: diff -uNr dmd-0.125/dmd/src/phobos/std/openrj.d dmd-0.126/dmd/src/phobos/std/openrj.d --- dmd-0.125/dmd/src/phobos/std/openrj.d 2005-05-20 15:41:14.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/std/openrj.d 2005-06-07 21:54:14.000000000 +0200 @@ -354,8 +354,8 @@ this(char[] name, char[] value/* , Record record */) in { - assert(null !== name); - assert(null !== value); + assert(null !is name); + assert(null !is value); } body { @@ -390,7 +390,7 @@ { Field f = cast(Field)(rhs); - if(null === f) + if(null is f) { throw new InvalidTypeException("Attempt to compare a Field with an instance of another type"); } @@ -402,7 +402,7 @@ { int res; - if(this === rhs) + if(this is rhs) { res = 0; } @@ -499,13 +499,13 @@ Field getField(char[] fieldName) in { - assert(null !== fieldName); + assert(null !is fieldName); } body { Field field = findField(fieldName); - if(null === field) + if(null is field) { throw new InvalidKeyException("field not found"); } @@ -516,18 +516,18 @@ Field findField(char[] fieldName) in { - assert(null !== fieldName); + assert(null !is fieldName); } body { Field *pfield = (fieldName in m_values); - return (null === pfield) ? null : *pfield; + return (null is pfield) ? null : *pfield; } int hasField(char[] fieldName) { - return null !== findField(fieldName); + return null !is findField(fieldName); } Database database() @@ -799,7 +799,7 @@ foreach(Record record; m_records) { - if(null !== record.findField(fieldName)) + if(null !is record.findField(fieldName)) { records ~= record; } @@ -817,7 +817,7 @@ { Field field = record.findField(fieldName); - if(null !== field) + if(null !is field) { // Since there can be more than one field with the same name in // the same record, we need to search all fields in this record @@ -829,7 +829,7 @@ int res = cmp(field.name, fieldName); if( 0 == res && - ( null === fieldValue || + ( null is fieldValue || field.value == fieldValue)) { records ~= record; @@ -847,7 +847,7 @@ foreach(Field field; record) { if( field.name == fieldName && - ( null === fieldValue || + ( null is fieldValue || field.value == fieldValue)) { records ~= record; diff -uNr dmd-0.125/dmd/src/phobos/std/perf.d dmd-0.126/dmd/src/phobos/std/perf.d --- dmd-0.125/dmd/src/phobos/std/perf.d 2005-05-20 15:41:14.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/std/perf.d 2005-06-07 21:54:12.000000000 +0200 @@ -44,7 +44,7 @@ this(T counter) in { - assert(null !== counter); + assert(null !is counter); } body { diff -uNr dmd-0.125/dmd/src/phobos/std/recls.d dmd-0.126/dmd/src/phobos/std/recls.d --- dmd-0.125/dmd/src/phobos/std/recls.d 2005-05-20 15:41:14.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/std/recls.d 2005-06-07 21:54:12.000000000 +0200 @@ -344,7 +344,7 @@ public char[] Search_GetEntryPath(in recls_info_t entry) in { - assert(null !== entry); + assert(null !is entry); } body { @@ -363,7 +363,7 @@ public char Search_GetEntryDrive(in recls_info_t entry) in { - assert(null !== entry); + assert(null !is entry); } body { @@ -376,7 +376,7 @@ public char[] Search_GetEntryDirectory(in recls_info_t entry) in { - assert(null !== entry); + assert(null !is entry); } body { @@ -393,7 +393,7 @@ public char[] Search_GetEntryDirectoryPath(in recls_info_t entry) in { - assert(null !== entry); + assert(null !is entry); } body { @@ -410,7 +410,7 @@ public char[] Search_GetEntryFile(in recls_info_t entry) in { - assert(null !== entry); + assert(null !is entry); } body { @@ -427,7 +427,7 @@ public char[] Search_GetEntryShortFile(in recls_info_t entry) in { - assert(null !== entry); + assert(null !is entry); } body { @@ -444,7 +444,7 @@ public char[] Search_GetEntryFileName(in recls_info_t entry) in { - assert(null !== entry); + assert(null !is entry); } body { @@ -461,7 +461,7 @@ public char[] Search_GetEntryFileExt(in recls_info_t entry) in { - assert(null !== entry); + assert(null !is entry); } body { @@ -478,7 +478,7 @@ public char[][] Search_GetEntryDirectoryParts(in recls_info_t entry) in { - assert(null !== entry); + assert(null !is entry); } body { @@ -503,7 +503,7 @@ public boolean Search_IsEntryReadOnly(in recls_info_t entry) in { - assert(null !== entry); + assert(null !is entry); } body { @@ -513,7 +513,7 @@ public boolean Search_IsEntryDirectory(in recls_info_t entry) in { - assert(null !== entry); + assert(null !is entry); } body { @@ -523,7 +523,7 @@ public boolean Search_IsEntryLink(in recls_info_t entry) in { - assert(null !== entry); + assert(null !is entry); } body { @@ -533,7 +533,7 @@ public recls_filesize_t Search_GetEntrySize(in recls_info_t entry) in { - assert(null !== entry); + assert(null !is entry); } body { @@ -545,7 +545,7 @@ public recls_time_t Search_GetEntryCreationTime(in recls_info_t entry) in { - assert(null !== entry); + assert(null !is entry); } body { @@ -555,7 +555,7 @@ public recls_time_t Search_GetEntryModificationTime(in recls_info_t entry) in { - assert(null !== entry); + assert(null !is entry); } body { @@ -565,7 +565,7 @@ public recls_time_t Search_GetEntryLastAccessTime(in recls_info_t entry) in { - assert(null !== entry); + assert(null !is entry); } body { @@ -575,7 +575,7 @@ public recls_time_t Search_GetEntryLastStatusChangeTime(in recls_info_t entry) in { - assert(null !== entry); + assert(null !is entry); } body { @@ -630,7 +630,7 @@ Entry CurrentEntry() in { - assert(null !== m_hSrch); + assert(null !is m_hSrch); } body { @@ -797,7 +797,7 @@ // we just add a reference, and then release it recls_info_t entry = Search_CopyEntry(m_entry); - assert(null !== entry); + assert(null !is entry); Recls_CloseDetails(entry); } @@ -834,7 +834,7 @@ } ~this() { - if(null !== m_entry) + if(null !is m_entry) { Search_CloseEntry(m_entry); } @@ -847,7 +847,7 @@ char[] GetPath() in { - assert(null !== m_entry); + assert(null !is m_entry); } body { @@ -859,7 +859,7 @@ char[] Path() in { - assert(null !== m_entry); + assert(null !is m_entry); } body { @@ -873,7 +873,7 @@ char Drive() in { - assert(null !== m_entry); + assert(null !is m_entry); } body { @@ -886,7 +886,7 @@ char[] Directory() in { - assert(null !== m_entry); + assert(null !is m_entry); } body { @@ -898,7 +898,7 @@ char[] DirectoryPath() in { - assert(null !== m_entry); + assert(null !is m_entry); } body { @@ -910,7 +910,7 @@ char[][] DirectoryParts() in { - assert(null !== m_entry); + assert(null !is m_entry); } body { @@ -922,7 +922,7 @@ char[] File() in { - assert(null !== m_entry); + assert(null !is m_entry); } body { @@ -934,7 +934,7 @@ char[] ShortFile() in { - assert(null !== m_entry); + assert(null !is m_entry); } body { @@ -946,7 +946,7 @@ char[] FileName() in { - assert(null !== m_entry); + assert(null !is m_entry); } body { @@ -958,7 +958,7 @@ char[] FileExt() in { - assert(null !== m_entry); + assert(null !is m_entry); } body { @@ -969,7 +969,7 @@ recls_time_t CreationTime() in { - assert(null !== m_entry); + assert(null !is m_entry); } body { @@ -979,7 +979,7 @@ recls_time_t ModificationTime() in { - assert(null !== m_entry); + assert(null !is m_entry); } body { @@ -989,7 +989,7 @@ recls_time_t LastAccessTime() in { - assert(null !== m_entry); + assert(null !is m_entry); } body { @@ -999,7 +999,7 @@ recls_time_t LastStatusChangeTime() in { - assert(null !== m_entry); + assert(null !is m_entry); } body { @@ -1010,7 +1010,7 @@ recls_filesize_t Size() in { - assert(null !== m_entry); + assert(null !is m_entry); } body { @@ -1021,7 +1021,7 @@ boolean IsReadOnly() in { - assert(null !== m_entry); + assert(null !is m_entry); } body { @@ -1031,7 +1031,7 @@ boolean IsDirectory() in { - assert(null !== m_entry); + assert(null !is m_entry); } body { @@ -1041,7 +1041,7 @@ boolean IsLink() in { - assert(null !== m_entry); + assert(null !is m_entry); } body { diff -uNr dmd-0.125/dmd/src/phobos/std/socket.d dmd-0.126/dmd/src/phobos/std/socket.d --- dmd-0.125/dmd/src/phobos/std/socket.d 2005-05-20 15:41:14.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/std/socket.d 2005-06-07 21:54:12.000000000 +0200 @@ -1339,12 +1339,12 @@ //make sure none of the SocketSet's are the same object if(checkRead) { - assert(checkRead !== checkWrite); - assert(checkRead !== checkError); + assert(checkRead !is checkWrite); + assert(checkRead !is checkError); } if(checkWrite) { - assert(checkWrite !== checkError); + assert(checkWrite !is checkError); } } body diff -uNr dmd-0.125/dmd/src/phobos/std/socketstream.d dmd-0.126/dmd/src/phobos/std/socketstream.d --- dmd-0.125/dmd/src/phobos/std/socketstream.d 2005-05-20 15:41:14.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/std/socketstream.d 2005-06-07 21:54:12.000000000 +0200 @@ -24,15 +24,11 @@ private import std.stream; private import std.socket; - class SocketStream: Stream { private: - bit prevCr = false; - bit atEof = false; Socket sock; - public: this(Socket sock, FileMode mode) { @@ -44,187 +40,61 @@ this.sock = sock; } - this(Socket sock) { writeable = readable = true; this.sock = sock; } - Socket socket() { return sock; } - override uint readBlock(void* _buffer, uint size) - in - { - assert(readable); - } - body - { - ubyte* buffer = cast(ubyte*)_buffer; - int len; - uint need = size; - - for(;;) - { - if(!need) - return size; - - len = sock.receive(buffer[0 .. need]); - if(len <= 0) - { - if(!len) - atEof = true; - break; - } - - buffer += len; - need -= len; - } - return size - need; - } - - - override char getc() - { - char ch; - - if(prevCr) - { - prevCr = false; - ch = super.getc(); - if(ch != '\n') - return ch; - } - - return super.getc(); - } - - - override wchar getcw() { - wchar ch; - - if(prevCr) - { - prevCr = false; - ch = super.getcw(); - if(ch != '\n') - return ch; - } - - return super.getcw(); + ubyte* buffer = cast(ubyte*)_buffer; + int len; + uint need = size; + assertReadable(); + + if(size == 0) + return size; + + len = sock.receive(buffer[0 .. size]); + readEOF = cast(bit)(len == 0); + if(len < 0) + len = 0; + return len; } - - override char[] readLine() - { - char[] result; - try - { - for(;;) - { - char ch = getc(); - switch(ch) - { - case '\r': - prevCr = true; - case '\n': - return result; - - default: - result ~= ch; - } - } - } - catch(ReadError re) - { - if(!eof()) - throw re; - } - return result; - } - - - override wchar[] readLineW() - { - wchar[] result; - try - { - for(;;) - { - char ch = getcw(); - switch(ch) - { - case '\r': - prevCr = true; - case '\n': - return result; - - default: - result ~= ch; - } - } - } - catch(ReadError re) - { - if(!eof()) - throw re; - } - return result; - } - - override uint writeBlock(void* _buffer, uint size) - in - { - assert(writeable); - } - body { - ubyte* buffer = cast(ubyte*)_buffer; - int len; - uint need = size; - - for(;;) - { - if(!need) - return size; - - len = sock.send(buffer[0 .. need]); - if(len <= 0) - break; - - buffer += len; - need -= len; - } - return size - need; + ubyte* buffer = cast(ubyte*)_buffer; + int len; + assertWriteable(); + + if(size == 0) + return size; + + len = sock.send(buffer[0 .. size]); + readEOF = cast(bit)(len == 0); + if(len < 0) + len = 0; + return len; } - override ulong seek(long offset, SeekPos whence) { - throw new SeekError("Cannot seek a socket."); + throw new SeekException("Cannot seek a socket."); return 0; } - override char[] toString() { return sock.toString(); } - - override bit eof() - { - return atEof; - } - - override void close() { sock.close(); diff -uNr dmd-0.125/dmd/src/phobos/std/stream.d dmd-0.126/dmd/src/phobos/std/stream.d --- dmd-0.125/dmd/src/phobos/std/stream.d 2005-05-20 15:41:14.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/std/stream.d 2005-06-07 21:54:12.000000000 +0200 @@ -63,12 +63,8 @@ End } -import std.format; -alias std.format.va_list va_list; -private import std.c.stdio; -alias std.c.stdio.va_list c_va_list; - private { + import std.format; import std.system; // for Endian enumeration import std.intrinsic; // for bswap import std.utf; @@ -150,10 +146,12 @@ // reads and returns next character from the stream, // handles characters pushed back by ungetc() + // return char.init on EOF char getc(); // reads and returns next Unicode character from the // stream, handles characters pushed back by ungetc() + // return wchar.init on EOF wchar getcw(); // pushes back character c into the stream; only has @@ -164,7 +162,7 @@ // has effect on further calls to getc() and getcw() wchar ungetcw(wchar c); - int vscanf(char[] fmt, c_va_list args); + int vscanf(char[] fmt, va_list args); int scanf(char[] format, ...); @@ -226,7 +224,7 @@ // writes data to stream using vprintf() syntax, // returns number of bytes written - size_t vprintf(char[] format, c_va_list args); + size_t vprintf(char[] format, va_list args); // writes data to stream using printf() syntax, // returns number of bytes written @@ -257,6 +255,9 @@ // flag that last readBlock resulted in eof protected bit readEOF = false; + // flag that last getc got \r + protected bit prevCr = false; + this() {} // reads block of data of specified size, @@ -331,35 +332,31 @@ // allocates a new string char[] readLine(char[] result) { size_t strlen = 0; - try { - char ch = getc(); - while (readable) { - switch (ch) { - case '\r': { + char ch = getc(); + while (readable) { + switch (ch) { + case '\r': + if (seekable) { ch = getc(); if (ch != '\n') ungetc(ch); + } else { + prevCr = true; } - - case '\n': - result.length = strlen; - return result; - - default: - if (strlen < result.length) { - result[strlen] = ch; - } else { - result ~= ch; - } - strlen++; + case '\n': + case char.init: + result.length = strlen; + return result; + + default: + if (strlen < result.length) { + result[strlen] = ch; + } else { + result ~= ch; } - ch = getc(); + strlen++; } - } catch (ReadException e) { - // either this is end of stream, which is okay, - // or something bad occured while reading - if (!eof()) - throw e; + ch = getc(); } result.length = strlen; return result; @@ -377,35 +374,31 @@ // fills supplied buffer if line fits and otherwise allocates a new string. wchar[] readLineW(wchar[] result) { size_t strlen = 0; - try { - wchar c = getcw(); - while (readable) { - switch (c) { - case '\r': { + wchar c = getcw(); + while (readable) { + switch (c) { + case '\r': + if (seekable) { c = getcw(); if (c != '\n') ungetcw(c); + } else { + prevCr = true; } - - case '\n': - result.length = strlen; - return result; - - default: - if (strlen < result.length) { - result[strlen] = c; - } else { - result ~= c; - } - strlen++; + case '\n': + case wchar.init: + result.length = strlen; + return result; + + default: + if (strlen < result.length) { + result[strlen] = c; + } else { + result ~= c; } - c = getcw(); + strlen++; } - } catch (ReadException e) { - // either this is end of stream, which is okay, - // or something bad occured while reading - if (!eof()) - throw e; + c = getcw(); } result.length = strlen; return result; @@ -485,26 +478,43 @@ // reads and returns next character from the stream, // handles characters pushed back by ungetc() + // returns char.init on eof. char getc() { char c; + if (prevCr) { + prevCr = false; + c = getc(); + if (c != '\n') + return c; + } if (unget.length > 1) { c = unget[unget.length - 1]; unget.length = unget.length - 1; } else { - read(c); + readBlock(&c,1); } return c; } // reads and returns next Unicode character from the // stream, handles characters pushed back by ungetc() + // returns wchar.init on eof. wchar getcw() { wchar c; + if (prevCr) { + prevCr = false; + c = getcw(); + if (c != '\n') + return c; + } if (unget.length > 1) { c = unget[unget.length - 1]; unget.length = unget.length - 1; } else { - read(c); + void* buf = &c; + size_t n = readBlock(buf,2); + if (n == 1 && readBlock(buf+1,1) == 0) + throw new ReadException("not enough data in stream"); } return c; } @@ -512,6 +522,7 @@ // pushes back character c into the stream; only has // effect on further calls to getc() and getcw() char ungetc(char c) { + if (c == c.init) return c; // first byte is a dummy so that we never set length to 0 if (unget.length == 0) unget.length = 1; @@ -522,6 +533,7 @@ // pushes back Unicode character c into the stream; only // has effect on further calls to getc() and getcw() wchar ungetcw(wchar c) { + if (c == c.init) return c; // first byte is a dummy so that we never set length to 0 if (unget.length == 0) unget.length = 1; @@ -529,300 +541,293 @@ return c; } - int vscanf(char[] fmt, c_va_list args) { + int vscanf(char[] fmt, va_list args) { void** arg = cast(void**) args; int count = 0, i = 0; - try { - char c = getc(); - while (i < fmt.length) { - if (fmt[i] == '%') { // a field + char c = getc(); + while (i < fmt.length && !eof()) { + if (fmt[i] == '%') { // a field + i++; + bit suppress = false; + if (fmt[i] == '*') { // suppress assignment + suppress = true; i++; - bit suppress = false; - if (fmt[i] == '*') { // suppress assignment - suppress = true; - i++; - } - // read field width - int width = 0; - while (isdigit(fmt[i])) { - width = width * 10 + (fmt[i] - '0'); + } + // read field width + int width = 0; + while (isdigit(fmt[i])) { + width = width * 10 + (fmt[i] - '0'); + i++; + } + if (width == 0) + width = -1; + // D string? + bit dstr = false; + if (fmt[i] == '.') { + i++; + if (fmt[i] == '*') { + dstr = true; i++; } - if (width == 0) - width = -1; - // D string? - bit dstr = false; - if (fmt[i] == '.') { - i++; - if (fmt[i] == '*') { - dstr = true; - i++; + } + // read the modifier + char modifier = fmt[i]; + if (modifier == 'h' || modifier == 'l' || modifier == 'L') + i++; + else + modifier = 0; + // check the typechar and act accordingly + switch (fmt[i]) { + case 'd': // decimal/hexadecimal/octal integer + case 'D': + case 'u': + case 'U': + case 'o': + case 'O': + case 'x': + case 'X': + case 'i': + case 'I': + { + while (iswhite(c)) { + c = getc(); + count++; } - } - // read the modifier - char modifier = fmt[i]; - if (modifier == 'h' || modifier == 'l' || modifier == 'L') - i++; - else - modifier = 0; - // check the typechar and act accordingly - switch (fmt[i]) { - case 'd': // decimal/hexadecimal/octal integer - case 'D': - case 'u': - case 'U': - case 'o': - case 'O': - case 'x': - case 'X': - case 'i': - case 'I': - { - while (iswhite(c)) { - c = getc(); - count++; - } - bit neg = false; - if (c == '-') { - neg = true; - c = getc(); - count++; - } else if (c == '+') { + bit neg = false; + if (c == '-') { + neg = true; + c = getc(); + count++; + } else if (c == '+') { + c = getc(); + count++; + } + char ifmt = fmt[i] | 0x20; + if (ifmt == 'i') { // undetermined base + if (c == '0') { // octal or hex c = getc(); count++; - } - char ifmt = fmt[i] | 0x20; - if (ifmt == 'i') { // undetermined base - if (c == '0') { // octal or hex + if (c == 'x' || c == 'X') { // hex + ifmt = 'x'; c = getc(); count++; - if (c == 'x' || c == 'X') { // hex - ifmt = 'x'; - c = getc(); - count++; - } else { // octal - ifmt = 'o'; - } + } else { // octal + ifmt = 'o'; } - else // decimal - ifmt = 'd'; } - long n = 0; - switch (ifmt) { - case 'd': // decimal - case 'u': { - while (isdigit(c) && width) { - n = n * 10 + (c - '0'); - width--; - c = getc(); - count++; - } - } break; - - case 'o': { // octal - while (isoctdigit(c) && width) { - n = n * 010 + (c - '0'); - width--; - c = getc(); - count++; - } - } break; - - case 'x': { // hexadecimal - while (ishexdigit(c) && width) { - n *= 0x10; - if (isdigit(c)) - n += c - '0'; - else - n += 0xA + (c | 0x20) - 'a'; - width--; - c = getc(); - count++; - } - } break; - } - if (neg) - n = -n; - // check the modifier and cast the pointer - // to appropriate type - switch (modifier) { - case 'h': { // short - *cast(short*)*arg = n; - } break; - - case 'L': { // long - *cast(long*)*arg = n; - } break; - - default: // int - *cast(int*)*arg = n; - } - i++; - } break; - - case 'f': // float - case 'F': - case 'e': - case 'E': - case 'g': - case 'G': - { - while (iswhite(c)) { - c = getc(); - count++; - } - bit neg = false; - if (c == '-') { - neg = true; - c = getc(); - count++; - } else if (c == '+') { - c = getc(); - count++; - } - real n = 0; + else // decimal + ifmt = 'd'; + } + long n = 0; + switch (ifmt) { + case 'd': // decimal + case 'u': { while (isdigit(c) && width) { n = n * 10 + (c - '0'); width--; c = getc(); count++; } - if (width && c == '.') { + } break; + + case 'o': { // octal + while (isoctdigit(c) && width) { + n = n * 010 + (c - '0'); width--; c = getc(); count++; - double frac = 1; - while (isdigit(c) && width) { - n = n * 10 + (c - '0'); - frac *= 10; - width--; - c = getc(); - count++; - } - n /= frac; } - if (width && (c == 'e' || c == 'E')) { + } break; + + case 'x': { // hexadecimal + while (ishexdigit(c) && width) { + n *= 0x10; + if (isdigit(c)) + n += c - '0'; + else + n += 0xA + (c | 0x20) - 'a'; width--; c = getc(); count++; - if (width) { - bit expneg = false; - if (c == '-') { - expneg = true; - width--; - c = getc(); - count++; - } else if (c == '+') { - width--; - c = getc(); - count++; - } - real exp = 0; - while (isdigit(c) && width) { - exp = exp * 10 + (c - '0'); - width--; - c = getc(); - count++; - } - if (expneg) { - while (exp--) - n /= 10; - } else { - while (exp--) - n *= 10; - } - } } - if (neg) - n = -n; - // check the modifier and cast the pointer - // to appropriate type - switch (modifier) { - case 'l': { // double - *cast(double*)*arg = n; - } break; - - case 'L': { // real - *cast(real*)*arg = n; - } break; + } break; + } + if (neg) + n = -n; + // check the modifier and cast the pointer + // to appropriate type + switch (modifier) { + case 'h': { // short + *cast(short*)*arg = n; + } break; - default: // float - *cast(float*)*arg = n; - } - i++; + case 'L': { // long + *cast(long*)*arg = n; } break; - case 's': { // ANSI string + default: // int + *cast(int*)*arg = n; + } + i++; + } break; + + case 'f': // float + case 'F': + case 'e': + case 'E': + case 'g': + case 'G': + { while (iswhite(c)) { c = getc(); count++; } - char[] s; - while (!iswhite(c)) { - s ~= c; + bit neg = false; + if (c == '-') { + neg = true; + c = getc(); + count++; + } else if (c == '+') { c = getc(); count++; } - if (dstr) // D string (char[]) - *cast(char[]*)*arg = s; - else { // C string (char*) - s ~= 0; - (cast(char*)*arg)[0 .. s.length] = s[]; + real n = 0; + while (isdigit(c) && width) { + n = n * 10 + (c - '0'); + width--; + c = getc(); + count++; } - i++; - } break; - - case 'c': { // character(s) - char* s = cast(char*)*arg; - if (width < 0) - width = 1; - else - while (iswhite(c)) { + if (width && c == '.') { + width--; c = getc(); count++; + double frac = 1; + while (isdigit(c) && width) { + n = n * 10 + (c - '0'); + frac *= 10; + width--; + c = getc(); + count++; + } + n /= frac; } - while (width--) { - *(s++) = c; + if (width && (c == 'e' || c == 'E')) { + width--; c = getc(); count++; + if (width) { + bit expneg = false; + if (c == '-') { + expneg = true; + width--; + c = getc(); + count++; + } else if (c == '+') { + width--; + c = getc(); + count++; + } + real exp = 0; + while (isdigit(c) && width) { + exp = exp * 10 + (c - '0'); + width--; + c = getc(); + count++; + } + if (expneg) { + while (exp--) + n /= 10; + } else { + while (exp--) + n *= 10; + } + } } - i++; - } break; + if (neg) + n = -n; + // check the modifier and cast the pointer + // to appropriate type + switch (modifier) { + case 'l': { // double + *cast(double*)*arg = n; + } break; + + case 'L': { // real + *cast(real*)*arg = n; + } break; - case 'n': { // number of chars read so far - *cast(int*)*arg = count; + default: // float + *cast(float*)*arg = n; + } i++; } break; - default: // read character as is - goto nws; + case 's': { // ANSI string + while (iswhite(c)) { + c = getc(); + count++; } - arg++; - } else if (iswhite(fmt[i])) { // skip whitespace - while (iswhite(c)) + char[] s; + while (!iswhite(c) && c != char.init) { + s ~= c; c = getc(); + count++; + } + if (dstr) // D string (char[]) + *cast(char[]*)*arg = s; + else { // C string (char*) + s ~= 0; + (cast(char*)*arg)[0 .. s.length] = s[]; + } i++; - } else { // read character as is - nws: - if (fmt[i] != c) - break; - c = getc(); + } break; + + case 'c': { // character(s) + char* s = cast(char*)*arg; + if (width < 0) + width = 1; + else + while (iswhite(c)) { + c = getc(); + count++; + } + while (width-- && !eof()) { + *(s++) = c; + c = getc(); + count++; + } i++; + } break; + + case 'n': { // number of chars read so far + *cast(int*)*arg = count; + i++; + } break; + + default: // read character as is + goto nws; } + arg++; + } else if (iswhite(fmt[i])) { // skip whitespace + while (iswhite(c)) + c = getc(); + i++; + } else { // read character as is + nws: + if (fmt[i] != c) + break; + c = getc(); + i++; } - ungetc(c); - } catch (ReadException e) { - // either this is end of stream, which is okay, - // or something bad occured while reading - if (!eof()) - throw e; } + ungetc(c); return count; } int scanf(char[] format, ...) { - c_va_list ap; - ap = cast(c_va_list) &format; + va_list ap; + ap = cast(va_list) &format; ap += format.sizeof; return vscanf(format, ap); } @@ -837,7 +842,14 @@ // writes block of data of specified size, // throws WriteException on error void writeExact(void* buffer, size_t size) { - if (writeBlock(buffer, size) != size) + for(;;) { + if (!size) return; + size_t writesize = writeBlock(buffer, size); + if (writesize == 0) break; + buffer += writesize; + size -= writesize; + } + if (size != 0) throw new WriteException("unable to write to stream"); } @@ -916,7 +928,7 @@ // writes data to stream using vprintf() syntax, // returns number of bytes written - size_t vprintf(char[] format, c_va_list args) { + size_t vprintf(char[] format, va_list args) { // shamelessly stolen from OutBuffer, // by Walter's permission char[1024] buffer; @@ -950,8 +962,8 @@ // writes data to stream using printf() syntax, // returns number of bytes written size_t printf(char[] format, ...) { - c_va_list ap; - ap = cast(c_va_list) &format; + va_list ap; + ap = cast(va_list) &format; ap += format.sizeof; return vprintf(format, ap); } @@ -1161,7 +1173,7 @@ } void updateAttribs() { - if (s !== null) { + if (s !is null) { readable = s.readable; writeable = s.writeable; seekable = s.seekable; @@ -1349,6 +1361,7 @@ } flush(); size_t res = s.readBlock(buffer,buffer.length); + readEOF = res == 0; if(!res) break L0; // EOF bufferSourcePos = bufferLen = res; streamPos += res; @@ -1580,15 +1593,6 @@ open(filename, mode | FileMode.OutNew); } - override void flush() { - super.flush(); - version (Win32) { - if (isopen && this !== .stdout) { - FlushFileBuffers(hFile); - } - } - } - // closes file, if it is open; otherwise, does nothing override void close() { if (isopen) { @@ -1972,6 +1976,27 @@ void read(out wchar x) { readExact(&x, x.sizeof); fixBO(&x,x.sizeof); } void read(out dchar x) { readExact(&x, x.sizeof); fixBO(&x,x.sizeof); } + wchar getcw() { + wchar c; + if (prevCr) { + prevCr = false; + c = getcw(); + if (c != '\n') + return c; + } + if (unget.length > 1) { + c = unget[unget.length - 1]; + unget.length = unget.length - 1; + } else { + void* buf = &c; + size_t n = readBlock(buf,2); + if (n == 1 && readBlock(buf+1,1) == 0) + throw new ReadException("not enough data in stream"); + fixBO(&c,c.sizeof); + } + return c; + } + wchar[] readStringW(size_t length) { wchar[] result = new wchar[length]; readExact(result, result.length * wchar.sizeof); @@ -2378,7 +2403,7 @@ // set the base stream and the low offset but leave the high unbounded. this (Stream base, ulong low) in { - assert (base !== null); + assert (base !is null); assert (low <= base.size ()); } body { @@ -2396,7 +2421,7 @@ // set the base stream, the low offset, and the high offset. this (Stream base, ulong low, ulong high) in { - assert (base !== null); + assert (base !is null); assert (low <= high); assert (high <= base.size ()); } @@ -2583,12 +2608,11 @@ } // standard IO devices -File stdin, stdout, stderr; +deprecated File stdin, stdout, stderr; version (Win32) { // API imports private extern(Windows) { - private import std.c.windows.windows; HANDLE GetStdHandle(DWORD); } diff -uNr dmd-0.125/dmd/src/phobos/std/string.d dmd-0.126/dmd/src/phobos/std/string.d --- dmd-0.125/dmd/src/phobos/std/string.d 2005-05-20 15:41:14.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/std/string.d 2005-06-07 21:54:12.000000000 +0200 @@ -199,12 +199,6 @@ char* toStringz(char[] string) in { - if (string) - { - // No embedded 0's - for (uint i = 0; i < string.length; i++) - assert(string[i] != 0); - } } out (result) { @@ -902,7 +896,7 @@ s2 = toupper(s1); assert(cmp(s2, "FOL") == 0); - assert(s2 !== s1); + assert(s2 !is s1); } @@ -958,7 +952,7 @@ s2 = capitalize(s1); assert(cmp(s2, "Fol") == 0); - assert(s2 !== s1); + assert(s2 !is s1); s2 = capitalize(s1[0 .. 2]); assert(cmp(s2, "Fo") == 0); @@ -967,7 +961,7 @@ s1 = "fOl"; s2 = capitalize(s1); assert(cmp(s2, "Fol") == 0); - assert(s2 !== s1); + assert(s2 !is s1); } diff -uNr dmd-0.125/dmd/src/phobos/std/thread.d dmd-0.126/dmd/src/phobos/std/thread.d --- dmd-0.125/dmd/src/phobos/std/thread.d 2005-05-20 15:41:14.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/std/thread.d 2005-06-07 21:54:12.000000000 +0200 @@ -228,7 +228,7 @@ { Thread t; t = allThreads[i]; - if (t && t !== tthis && t.state == TS.RUNNING) + if (t && t !is tthis && t.state == TS.RUNNING) t.pause(); } } @@ -244,7 +244,7 @@ { Thread t; t = allThreads[i]; - if (t && t !== tthis && t.state == TS.RUNNING) + if (t && t !is tthis && t.state == TS.RUNNING) t.resume(); } } @@ -664,7 +664,7 @@ { Thread t; t = allThreads[i]; - if (t && t !== tthis && t.state == TS.RUNNING) + if (t && t !is tthis && t.state == TS.RUNNING) { int result; result = pthread_kill(t.id, SIGUSR1); @@ -693,7 +693,7 @@ { Thread t; t = allThreads[i]; - if (t && t !== tthis && t.state == TS.RUNNING) + if (t && t !is tthis && t.state == TS.RUNNING) t.resume(); } } @@ -776,7 +776,24 @@ t.state = TS.RUNNING; t.id = pthread_self(); - t.stackBottom = cast(void*)__libc_stack_end; + + version (none) + { + // See discussion: http://autopackage.org/forums/viewtopic.php?t=22 + static void** libc_stack_end; + + if (libc_stack_end == libc_stack_end.init) + { + void* handle = dlopen(null, RTLD_NOW); + libc_stack_end = cast(void **)dlsym(handle, "__libc_stack_end"); + dlclose(handle); + } + t.stackBottom = *libc_stack_end; + } + else + { + t.stackBottom = cast(void*)__libc_stack_end; + } assert(!allThreads[0]); allThreads[0] = t; diff -uNr dmd-0.125/dmd/src/phobos/unittest.d dmd-0.126/dmd/src/phobos/unittest.d --- dmd-0.125/dmd/src/phobos/unittest.d 2005-05-20 15:41:14.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/unittest.d 2005-06-07 21:54:12.000000000 +0200 @@ -37,6 +37,7 @@ import std.random; import std.date; import std.dateparse; +import std.cstream; import std.stream; import std.utf; import std.uri; @@ -67,7 +68,8 @@ a.reverse; // adi a.sort; // qsort std.date.getUTCtime(); // date - StreamError se = new StreamError(""); // stream + Exception e = new ReadException(""); // stream + din.eof(); // cstream isValidDchar(cast(dchar)0); // utf std.uri.ascii2hex(0); // uri std.zlib.adler32(0,null); // D.zlib diff -uNr dmd-0.125/dmd/src/phobos/win32.mak dmd-0.126/dmd/src/phobos/win32.mak --- dmd-0.125/dmd/src/phobos/win32.mak 2005-05-20 15:41:12.000000000 +0200 +++ dmd-0.126/dmd/src/phobos/win32.mak 2005-06-07 21:54:12.000000000 +0200 @@ -65,7 +65,7 @@ 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 \ + errno.obj boxer.obj cstream.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,8 @@ std\intrinsic.d std\array.d std\switcherr.d std\syserror.d \ 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\stdio.d std\perf.d std\openrj.d std\uni.d std\boxer.d \ + std\cstream.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 @@ -445,6 +446,9 @@ conv.obj : std\conv.d $(DMD) -c $(DFLAGS) std\conv.d +cstream.obj : std\cstream.d + $(DMD) -c $(DFLAGS) std\cstream.d + ctype.obj : std\ctype.d $(DMD) -c $(DFLAGS) std\ctype.d @@ -521,7 +525,7 @@ $(DMD) -c $(DFLAGS) std\stdio.d stream.obj : std\stream.d - $(DMD) -c $(DFLAGS) std\stream.d + $(DMD) -c $(DFLAGS) -d std\stream.d string.obj : std\string.d $(DMD) -c $(DFLAGS) std\string.d