diff -uNr dmd-0.121/dmd/src/dmd/attrib.c dmd-0.122/dmd/src/dmd/attrib.c --- dmd-0.121/dmd/src/dmd/attrib.c 2005-04-12 21:51:34.000000000 +0200 +++ dmd-0.122/dmd/src/dmd/attrib.c 2005-04-25 10:51:08.000000000 +0200 @@ -443,9 +443,10 @@ /********************************* AnonDeclaration ****************************/ -AnonDeclaration::AnonDeclaration(int isunion, Array *decl) +AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Array *decl) : AttribDeclaration(decl) { + this->loc = loc; this->isunion = isunion; } @@ -454,7 +455,7 @@ AnonDeclaration *ad; assert(!s); - ad = new AnonDeclaration(isunion, Dsymbol::arraySyntaxCopy(decl)); + ad = new AnonDeclaration(loc, isunion, Dsymbol::arraySyntaxCopy(decl)); return ad; } diff -uNr dmd-0.121/dmd/src/dmd/attrib.h dmd-0.122/dmd/src/dmd/attrib.h --- dmd-0.121/dmd/src/dmd/attrib.h 2005-04-12 10:17:32.000000000 +0200 +++ dmd-0.122/dmd/src/dmd/attrib.h 2005-04-25 10:48:38.000000000 +0200 @@ -91,7 +91,7 @@ { int isunion; - AnonDeclaration(int isunion, Array *decl); + AnonDeclaration(Loc loc, int isunion, Array *decl); Dsymbol *syntaxCopy(Dsymbol *s); void semantic(Scope *sc); void toCBuffer(OutBuffer *buf); diff -uNr dmd-0.121/dmd/src/dmd/class.c dmd-0.122/dmd/src/dmd/class.c --- dmd-0.121/dmd/src/dmd/class.c 2005-04-13 10:08:10.000000000 +0200 +++ dmd-0.122/dmd/src/dmd/class.c 2005-05-03 21:33:18.000000000 +0200 @@ -69,7 +69,7 @@ Module::moduleinfo = this; // BUG: What if this is the wrong TypeInfo, i.e. it is nested? - if (id->toChars()[0] == 'T') + if (id && id->toChars()[0] == 'T') { if (!Type::typeinfo && id == Id::TypeInfo) Type::typeinfo = this; @@ -193,12 +193,16 @@ ; else { - if (tc->sym == this) + for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass) { - error("base class same as class"); - baseclasses.remove(0); + if (cdb == this) + { + error("circular inheritance"); + baseclasses.remove(0); + goto L7; + } } - else if (!tc->sym->symtab || tc->sym->scope) + if (!tc->sym->symtab || tc->sym->scope) { //error("forward reference of base class %s", baseClass->toChars()); // Forward reference of base class, try again later @@ -212,6 +216,7 @@ { baseClass = tc->sym; b->base = baseClass; } + L7: ; } } } @@ -817,7 +822,7 @@ { unsigned j; - //printf("InterfaceDeclaration::isBaseOf(cd = '%s')\n", cd->toChars()); + //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars()); assert(!baseClass); for (j = 0; j < cd->interfaces_dim; j++) { @@ -851,7 +856,7 @@ int InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset) { - //printf("InterfaceDeclaration::isBaseOf(bc = '%s')\n", bc->base->toChars()); + //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base->toChars()); for (unsigned j = 0; j < bc->baseInterfaces_dim; j++) { BaseClass *b = &bc->baseInterfaces[j]; @@ -984,9 +989,14 @@ void BaseClass::copyBaseInterfaces(Array *vtblInterfaces) { + if (baseInterfaces_dim) + { error("circular inheritance of interface"); + return; + } baseInterfaces_dim = base->interfaces_dim; baseInterfaces = (BaseClass *)mem.calloc(baseInterfaces_dim, sizeof(BaseClass)); + //printf("%s.copyBaseInterfaces()\n", base->toChars()); for (int i = 0; i < baseInterfaces_dim; i++) { BaseClass *b = &baseInterfaces[i]; diff -uNr dmd-0.121/dmd/src/dmd/debcond.c dmd-0.122/dmd/src/dmd/debcond.c --- dmd-0.121/dmd/src/dmd/debcond.c 2005-04-05 21:00:54.000000000 +0200 +++ dmd-0.122/dmd/src/dmd/debcond.c 2005-04-24 02:03:28.000000000 +0200 @@ -111,7 +111,7 @@ global.params.versionlevel = level; } -void VersionCondition::checkPredefined(char *ident) +void VersionCondition::checkPredefined(Loc loc, char *ident) { static char* reserved[] = { @@ -135,12 +135,12 @@ return; Lerror: - error("version identifier '%s' is reserved and cannot be set", ident); + error(loc, "version identifier '%s' is reserved and cannot be set", ident); } void VersionCondition::addGlobalIdent(char *ident) { - checkPredefined(ident); + checkPredefined(0, ident); addPredefinedGlobalIdent(ident); } diff -uNr dmd-0.121/dmd/src/dmd/debcond.h dmd-0.122/dmd/src/dmd/debcond.h --- dmd-0.121/dmd/src/dmd/debcond.h 2005-03-18 00:07:06.000000000 +0100 +++ dmd-0.122/dmd/src/dmd/debcond.h 2005-04-24 02:05:46.000000000 +0200 @@ -43,7 +43,7 @@ struct VersionCondition : Condition { static void setGlobalLevel(unsigned level); - static void checkPredefined(char *ident); + static void checkPredefined(Loc loc, char *ident); static void addGlobalIdent(char *ident); static void addPredefinedGlobalIdent(char *ident); diff -uNr dmd-0.121/dmd/src/dmd/declaration.c dmd-0.122/dmd/src/dmd/declaration.c --- dmd-0.121/dmd/src/dmd/declaration.c 2005-04-12 23:16:58.000000000 +0200 +++ dmd-0.122/dmd/src/dmd/declaration.c 2005-04-24 11:21:40.000000000 +0200 @@ -79,13 +79,14 @@ /********************************* TypedefDeclaration ****************************/ -TypedefDeclaration::TypedefDeclaration(Identifier *id, Type *basetype, Initializer *init) +TypedefDeclaration::TypedefDeclaration(Loc loc, Identifier *id, Type *basetype, Initializer *init) : Declaration(id) { this->type = new TypeTypedef(this); this->basetype = basetype->toBasetype(); this->init = init; this->sem = 0; + this->loc = loc; } Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s) @@ -98,7 +99,7 @@ assert(!s); TypedefDeclaration *st; - st = new TypedefDeclaration(ident, basetype, init); + st = new TypedefDeclaration(loc, ident, basetype, init); return st; } diff -uNr dmd-0.121/dmd/src/dmd/declaration.h dmd-0.122/dmd/src/dmd/declaration.h --- dmd-0.121/dmd/src/dmd/declaration.h 2005-04-12 23:16:00.000000000 +0200 +++ dmd-0.122/dmd/src/dmd/declaration.h 2005-04-24 11:21:38.000000000 +0200 @@ -110,7 +110,7 @@ // 2: semantic() has been run // 3: semantic2() has been run - TypedefDeclaration(Identifier *ident, Type *basetype, Initializer *init); + TypedefDeclaration(Loc loc, Identifier *ident, Type *basetype, Initializer *init); Dsymbol *syntaxCopy(Dsymbol *); void semantic(Scope *sc); void semantic2(Scope *sc); diff -uNr dmd-0.121/dmd/src/dmd/dsymbol.c dmd-0.122/dmd/src/dmd/dsymbol.c --- dmd-0.121/dmd/src/dmd/dsymbol.c 2005-04-12 22:55:12.000000000 +0200 +++ dmd-0.122/dmd/src/dmd/dsymbol.c 2005-04-25 10:53:28.000000000 +0200 @@ -294,7 +294,10 @@ printf("%s: ", p); mem.free(p); - printf("%s %s ", kind(), toPrettyChars()); + if (isAnonymous()) + printf("%s ", kind()); + else + printf("%s %s ", kind(), toPrettyChars()); va_list ap; va_start(ap, format); diff -uNr dmd-0.121/dmd/src/dmd/expression.c dmd-0.122/dmd/src/dmd/expression.c --- dmd-0.121/dmd/src/dmd/expression.c 2005-04-14 21:38:30.000000000 +0200 +++ dmd-0.122/dmd/src/dmd/expression.c 2005-05-03 15:08:06.000000000 +0200 @@ -77,7 +77,7 @@ } if (!fd->isThis()) - { //printf("test2 '%s'\n", fd->toChars()); + { //printf("test '%s'\n", fd->toChars()); goto Lno; } @@ -3383,36 +3383,51 @@ type = Type::tvoid; tb = e1->type->toBasetype(); - if (tb->ty == Tclass) - { - TypeClass *tc = (TypeClass *)tb; - ClassDeclaration *cd = tc->sym; + switch (tb->ty) + { case Tclass: + { TypeClass *tc = (TypeClass *)tb; + ClassDeclaration *cd = tc->sym; - if (cd->isInterfaceDeclaration() && cd->isCOMclass()) - error("cannot delete instance of COM interface %s", cd->toChars()); - } - else if (tb->ty == Tpointer) - { - tb = tb->next->toBasetype(); - if (tb->ty == Tstruct) - { - TypeStruct *ts = (TypeStruct *)tb; - StructDeclaration *sd = ts->sym; - FuncDeclaration *f = sd->aggDelete; + if (cd->isInterfaceDeclaration() && cd->isCOMclass()) + error("cannot delete instance of COM interface %s", cd->toChars()); + break; + } + case Tpointer: + tb = tb->next->toBasetype(); + if (tb->ty == Tstruct) + { + TypeStruct *ts = (TypeStruct *)tb; + StructDeclaration *sd = ts->sym; + FuncDeclaration *f = sd->aggDelete; - if (f) + if (f) + { + Expression *e; + Expression *ec; + Type *tpv = Type::tvoid->pointerTo(); + + e = e1; + e->type = tpv; + ec = new VarExp(loc, f); + e = new CallExp(loc, ec, e); + return e->semantic(sc); + } + } + break; + + case Tarray: + break; + + default: + if (e1->op == TOKindex) { - Expression *e; - Expression *ec; - Type *tpv = Type::tvoid->pointerTo(); - - e = e1; - e->type = tpv; - ec = new VarExp(loc, f); - e = new CallExp(loc, ec, e); - return e->semantic(sc); + IndexExp *ae = (IndexExp *)(e1); + Type *tb1 = ae->e1->type->toBasetype(); + if (tb1->ty == Taarray) + break; } - } + error("cannot delete type %s", e1->type->toChars()); + break; } return this; } @@ -4711,7 +4726,8 @@ */ typeCombine(); - + if (type->toBasetype()->ty == Tsarray) + type = type->toBasetype()->next->arrayOf(); #if 0 e1->type->print(); e2->type->print(); @@ -5196,6 +5212,11 @@ error("need member function opCmp() for struct %s to compare", t1->toChars()); e = this; } + else if (t1->iscomplex() || t2->iscomplex()) + { + error("compare not defined for complex operands"); + e = new IntegerExp(0); + } else e = this; return e; diff -uNr dmd-0.121/dmd/src/dmd/func.c dmd-0.122/dmd/src/dmd/func.c --- dmd-0.121/dmd/src/dmd/func.c 2005-04-14 22:12:18.000000000 +0200 +++ dmd-0.122/dmd/src/dmd/func.c 2005-05-02 22:17:26.000000000 +0200 @@ -736,7 +736,7 @@ } if (inv) { - e = new DsymbolExp(0, ad->inv); + e = new DsymbolExp(0, inv); e = new CallExp(0, e); e = e->semantic(sc2); } @@ -1044,6 +1044,7 @@ error(loc, "%s does not match argument types (%s)", Argument::argsTypesToChars(tf->arguments, tf->varargs), buf.toChars()); +*(char*)0=0; return m.anyf; // as long as it's not a FuncAliasDeclaration } else @@ -1685,7 +1686,7 @@ error("invariants only are for struct/union/class definitions"); return; } - else if (ad->inv) + else if (ad->inv && ad->inv != this) { error("more than one invariant for %s", ad->toChars()); } diff -uNr dmd-0.121/dmd/src/dmd/html.c dmd-0.122/dmd/src/dmd/html.c --- dmd-0.121/dmd/src/dmd/html.c 2005-04-01 16:09:30.000000000 +0200 +++ dmd-0.122/dmd/src/dmd/html.c 2005-04-26 15:23:58.000000000 +0200 @@ -373,6 +373,12 @@ int scangt = 0; //printf("scanComment()\n"); + if (*p == '\n') + { linnum++; + // Always extract new lines, so that D lexer counts the + // lines right. + dbuf->writeByte(*p); + } while (1) { //scangt = 1; // IE 5.0 compatibility diff -uNr dmd-0.121/dmd/src/dmd/import.c dmd-0.122/dmd/src/dmd/import.c --- dmd-0.121/dmd/src/dmd/import.c 2005-02-20 19:11:38.000000000 +0100 +++ dmd-0.122/dmd/src/dmd/import.c 2005-04-29 16:22:00.000000000 +0200 @@ -49,33 +49,54 @@ return si; } - -void Import::semantic(Scope *sc) +void Import::load() { DsymbolTable *dst; Dsymbol *s; - //printf("Import::semantic('%s')\n", toChars()); + //printf("Import::load('%s')\n", toChars()); // See if existing module dst = Package::resolve(packages, NULL, &pkg); s = dst->lookup(id); - if (s && !s->isModule()) - error("package and module have the same name"); - else + if (s) { - mod = (Module *)s; - if (!mod) - { - // Load module - mod = Module::load(loc, packages, id); + if (s->isModule()) + mod = (Module *)s; + else + error("package and module have the same name"); + } + + if (!mod) + { + // Load module + mod = Module::load(loc, packages, id); + dst->insert(id, mod); // id may be different from mod->ident, + // if so then insert alias + } + if (!pkg) + pkg = mod; + mod->semantic(); + + //printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg); +} + + +void Import::semantic(Scope *sc) +{ + //printf("Import::semantic('%s')\n", toChars()); + + load(); + + if (mod) + { + if (mod->loc.linnum != 0) + /* If the line number is not 0, then this is not + * a 'root' module, i.e. it was not specified on the command line. + */ mod->importedFrom = sc->module->importedFrom; - dst->insert(id, mod); // id may be different from mod->ident, - // if so then insert alias - } - mod->semantic(); - //printf("import '%s', protection = %d for '%s'\n", toChars(), sc->protection, mod->toChars()); + sc->scopesym->importScope(mod, sc->protection); // Modules need a list of each imported module @@ -84,11 +105,7 @@ if (mod->needmoduleinfo) sc->module->needmoduleinfo = 1; } - if (!pkg) - pkg = mod; - -// if (sc->module) -// sc->module->needmoduleinfo = 1; + //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg); } void Import::semantic2(Scope *sc) @@ -100,6 +117,11 @@ Dsymbol *Import::search(Identifier *ident, int flags) { + //printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags); + + if (!pkg) + load(); + // Forward it to the package/module return pkg->search(ident, flags); } diff -uNr dmd-0.121/dmd/src/dmd/import.h dmd-0.122/dmd/src/dmd/import.h --- dmd-0.121/dmd/src/dmd/import.h 2003-12-19 22:36:38.000000000 +0100 +++ dmd-0.122/dmd/src/dmd/import.h 2005-04-29 16:18:56.000000000 +0200 @@ -33,6 +33,7 @@ Import(Loc loc, Array *packages, Identifier *id); char *kind(); Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees + void load(); void semantic(Scope *sc); void semantic2(Scope *sc); Dsymbol *search(Identifier *ident, int flags); diff -uNr dmd-0.121/dmd/src/dmd/init.c dmd-0.122/dmd/src/dmd/init.c --- dmd-0.121/dmd/src/dmd/init.c 2005-04-13 15:37:54.000000000 +0200 +++ dmd-0.122/dmd/src/dmd/init.c 2005-04-26 17:27:28.000000000 +0200 @@ -257,9 +257,14 @@ val = val->semantic(sc, t->next); value.data[i] = (void *)val; length++; + if (length == 0) + error("array dimension overflow"); if (length > dim) dim = length; } + unsigned long amax = 0x80000000; + if ((unsigned long) dim * t->next->size() >= amax) + error(loc, "array dimension %u exceeds max of %lu", dim, amax / t->next->size()); return this; } diff -uNr dmd-0.121/dmd/src/dmd/lexer.c dmd-0.122/dmd/src/dmd/lexer.c --- dmd-0.121/dmd/src/dmd/lexer.c 2005-04-08 21:06:48.000000000 +0200 +++ dmd-0.122/dmd/src/dmd/lexer.c 2005-04-24 22:55:46.000000000 +0200 @@ -1894,12 +1894,16 @@ case '\n': Lnewline: loc.linnum = linnum; + if (filespec) + loc.filename = filespec; return; case '\r': p++; if (*p != '\n') - loc.linnum = linnum; + { p--; + goto Lnewline; + } continue; case ' ': @@ -1929,7 +1933,6 @@ case '"': stringbuffer.writeByte(0); filespec = mem.strdup((char *)stringbuffer.data); - loc.filename = filespec; p++; break; diff -uNr dmd-0.121/dmd/src/dmd/mars.c dmd-0.122/dmd/src/dmd/mars.c --- dmd-0.121/dmd/src/dmd/mars.c 2005-04-08 21:06:06.000000000 +0200 +++ dmd-0.122/dmd/src/dmd/mars.c 2005-04-24 01:34:02.000000000 +0200 @@ -49,7 +49,7 @@ copyright = "Copyright (c) 1999-2005 by Digital Mars"; written = "written by Walter Bright"; - version = "v0.121"; + version = "v0.122"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); diff -uNr dmd-0.121/dmd/src/dmd/mars.h dmd-0.122/dmd/src/dmd/mars.h --- dmd-0.121/dmd/src/dmd/mars.h 2005-04-05 21:01:30.000000000 +0200 +++ dmd-0.122/dmd/src/dmd/mars.h 2005-04-27 01:14:06.000000000 +0200 @@ -190,6 +190,7 @@ void error(Loc loc, const char *format, ...); void fatal(); +void err_nomem(); int runLINK(); void inifile(char *argv0, char *inifile); diff -uNr dmd-0.121/dmd/src/dmd/mem.c dmd-0.122/dmd/src/dmd/mem.c --- dmd-0.121/dmd/src/dmd/mem.c 2004-03-27 00:11:52.000000000 +0100 +++ dmd-0.122/dmd/src/dmd/mem.c 2005-04-27 01:21:12.000000000 +0200 @@ -127,7 +127,12 @@ void * operator new(size_t m_size) { - return malloc(m_size); + void *p = malloc(m_size); + if (p) + return p; + printf("Error: out of memory\n"); + exit(EXIT_FAILURE); + return p; } void operator delete(void *p) diff -uNr dmd-0.121/dmd/src/dmd/parse.c dmd-0.122/dmd/src/dmd/parse.c --- dmd-0.121/dmd/src/dmd/parse.c 2005-04-12 22:25:20.000000000 +0200 +++ dmd-0.122/dmd/src/dmd/parse.c 2005-04-25 10:50:04.000000000 +0200 @@ -400,9 +400,9 @@ { nextToken(); if (token.value == TOKidentifier) - s = new DebugSymbol(token.ident); + s = new DebugSymbol(loc, token.ident); else if (token.value == TOKint32v) - s = new DebugSymbol((unsigned)token.uns64value); + s = new DebugSymbol(loc, (unsigned)token.uns64value); else { error("identifier or integer expected, not %s", token.toChars()); s = NULL; @@ -441,9 +441,9 @@ { nextToken(); if (token.value == TOKidentifier) - s = new VersionSymbol(token.ident); + s = new VersionSymbol(loc, token.ident); else if (token.value == TOKint32v) - s = new VersionSymbol((unsigned)token.uns64value); + s = new VersionSymbol(loc, (unsigned)token.uns64value); else { error("identifier or integer expected, not %s", token.toChars()); s = NULL; @@ -930,6 +930,7 @@ } } + Loc loc = this->loc; switch (tok) { case TOKclass: case TOKinterface: @@ -1020,7 +1021,7 @@ { /* Anonymous structs/unions are more like attributes. */ - return new AnonDeclaration(anon - 1, decl); + return new AnonDeclaration(loc, anon - 1, decl); } else a->members = decl; @@ -1902,7 +1903,7 @@ init = parseInitializer(); } if (tok == TOKtypedef) - v = new TypedefDeclaration(ident, t, init); + v = new TypedefDeclaration(loc, ident, t, init); else { if (init) error("alias cannot have initializer"); diff -uNr dmd-0.121/dmd/src/dmd/struct.c dmd-0.122/dmd/src/dmd/struct.c --- dmd-0.121/dmd/src/dmd/struct.c 2005-04-12 22:00:30.000000000 +0200 +++ dmd-0.122/dmd/src/dmd/struct.c 2005-05-02 22:32:14.000000000 +0200 @@ -309,8 +309,10 @@ e = new IdentifierExp(loc, id); e = new CallExp(loc, e, args); fdptr->fbody = new ReturnStatement(loc, e); - members->push(fdptr); - fdptr->addMember(this); + ScopeDsymbol *s = fdx->parent->isScopeDsymbol(); + assert(s); + s->members->push(fdptr); + fdptr->addMember(s); fdptr->semantic(sc2); } } diff -uNr dmd-0.121/dmd/src/dmd/todt.c dmd-0.122/dmd/src/dmd/todt.c --- dmd-0.121/dmd/src/dmd/todt.c 2005-03-09 23:15:46.000000000 +0100 +++ dmd-0.122/dmd/src/dmd/todt.c 2005-04-27 01:23:24.000000000 +0200 @@ -175,8 +175,9 @@ idx = (Expression *)index.data[i]; if (idx) length = idx->toInteger(); - //printf("index[%d] = %p, length = %d\n", i, idx, length); + //printf("index[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim); + assert(length < dim); val = (Initializer *)value.data[i]; dt = val->toDt(); if (dts.data[length]) @@ -723,10 +724,16 @@ else { next->toDt(pdt); + dt_optimize(*pdt); if ((*pdt)->dt == DT_azeros && !(*pdt)->DTnext) { (*pdt)->DTazeros *= len; } + else if ((*pdt)->dt == DT_1byte && (*pdt)->DTonebyte == 0 && !(*pdt)->DTnext) + { + (*pdt)->dt = DT_azeros; + (*pdt)->DTazeros = len; + } else { for (i = 1; i < len; i++) diff -uNr dmd-0.121/dmd/src/dmd/version.c dmd-0.122/dmd/src/dmd/version.c --- dmd-0.121/dmd/src/dmd/version.c 2005-04-12 23:32:20.000000000 +0200 +++ dmd-0.122/dmd/src/dmd/version.c 2005-04-24 02:05:48.000000000 +0200 @@ -19,21 +19,23 @@ /* ================================================== */ -DebugSymbol::DebugSymbol(Identifier *ident) +DebugSymbol::DebugSymbol(Loc loc, Identifier *ident) : Dsymbol(ident) { + this->loc = loc; } -DebugSymbol::DebugSymbol(unsigned level) +DebugSymbol::DebugSymbol(Loc loc, unsigned level) : Dsymbol() { this->level = level; + this->loc = loc; } Dsymbol *DebugSymbol::syntaxCopy(Dsymbol *s) { assert(!s); - DebugSymbol *ds = new DebugSymbol(ident); + DebugSymbol *ds = new DebugSymbol(loc, ident); ds->level = level; return ds; } @@ -89,21 +91,23 @@ /* ================================================== */ -VersionSymbol::VersionSymbol(Identifier *ident) +VersionSymbol::VersionSymbol(Loc loc, Identifier *ident) : Dsymbol(ident) { + this->loc = loc; } -VersionSymbol::VersionSymbol(unsigned level) +VersionSymbol::VersionSymbol(Loc loc, unsigned level) : Dsymbol() { this->level = level; + this->loc = loc; } Dsymbol *VersionSymbol::syntaxCopy(Dsymbol *s) { assert(!s); - VersionSymbol *ds = new VersionSymbol(ident); + VersionSymbol *ds = new VersionSymbol(loc, ident); ds->level = level; return ds; } @@ -118,7 +122,7 @@ m = sd->isModule(); if (ident) { - VersionCondition::checkPredefined(ident->toChars()); + VersionCondition::checkPredefined(loc, ident->toChars()); if (!m) error("declaration must be at module level"); else diff -uNr dmd-0.121/dmd/src/dmd/version.h dmd-0.122/dmd/src/dmd/version.h --- dmd-0.121/dmd/src/dmd/version.h 2005-04-12 23:32:22.000000000 +0200 +++ dmd-0.122/dmd/src/dmd/version.h 2005-04-24 02:03:58.000000000 +0200 @@ -22,8 +22,8 @@ { unsigned level; - DebugSymbol(Identifier *ident); - DebugSymbol(unsigned level); + DebugSymbol(Loc loc, Identifier *ident); + DebugSymbol(Loc loc, unsigned level); Dsymbol *syntaxCopy(Dsymbol *); void addMember(ScopeDsymbol *s); @@ -36,8 +36,8 @@ { unsigned level; - VersionSymbol(Identifier *ident); - VersionSymbol(unsigned level); + VersionSymbol(Loc loc, Identifier *ident); + VersionSymbol(Loc loc, unsigned level); Dsymbol *syntaxCopy(Dsymbol *); void addMember(ScopeDsymbol *s); diff -uNr dmd-0.121/dmd/src/phobos/internal/arraycat.d dmd-0.122/dmd/src/phobos/internal/arraycat.d --- dmd-0.121/dmd/src/phobos/internal/arraycat.d 2005-04-15 14:30:50.000000000 +0200 +++ dmd-0.122/dmd/src/phobos/internal/arraycat.d 2005-05-04 12:26:36.000000000 +0200 @@ -28,25 +28,6 @@ extern (C): -byte[] _d_arraycat(byte[] x, byte[] y, uint size) -{ byte[] a; - uint length; - - if (!x.length) - return y; - if (!y.length) - return x; - - length = x.length + y.length; - a = new byte[length * size]; - memcpy(a, x, x.length * size); - //a[0 .. x.length * size] = x[]; - memcpy(&a[x.length * size], y, y.length * size); - *cast(int *)&a = length; // jam length - //a.length = length; - return a; -} - byte[] _d_arraycatn(uint size, uint n, ...) { byte[] a; uint length; diff -uNr dmd-0.121/dmd/src/phobos/internal/gc/gc.d dmd-0.122/dmd/src/phobos/internal/gc/gc.d --- dmd-0.121/dmd/src/phobos/internal/gc/gc.d 2005-04-15 14:30:52.000000000 +0200 +++ dmd-0.122/dmd/src/phobos/internal/gc/gc.d 2005-05-04 12:26:38.000000000 +0200 @@ -202,7 +202,7 @@ result = 0; else { - p = _gc.malloc(length * size); + p = _gc.malloc(length * size + 1); debug(PRINTF) printf(" p = %p\n", p); memset(p, 0, length * size); result = cast(ulong)length + (cast(ulong)cast(uint)p << 32); @@ -215,12 +215,12 @@ void *p; ulong result; - debug(PRINTF) printf("_d_newarrayi(length = %d, size = %d)\n", length, size); + //debug(PRINTF) printf("_d_newarrayi(length = %d, size = %d)\n", length, size); if (length == 0 || size == 0) result = 0; else { void* q = cast(void*)(&size + 1); // pointer to initializer - p = _gc.malloc(length * size); + p = _gc.malloc(length * size + 1); debug(PRINTF) printf(" p = %p\n", p); if (size == 1) memset(p, *cast(ubyte*)q, length); @@ -245,7 +245,7 @@ if (length == 0) result = 0; else - { uint size = (length + 7) >> 3; // number of bytes + { uint size = (length + 8) >> 3; // number of bytes ubyte fill = value ? 0xFF : 0; p = _gc.malloc(size); @@ -361,9 +361,9 @@ if (newsize > size) { uint cap = _gc.capacity(p.data); - if (cap < newsize) + if (cap <= newsize) { - newdata = cast(byte *)_gc.malloc(newsize); + newdata = cast(byte *)_gc.malloc(newsize + 1); newdata[0 .. size] = p.data[0 .. size]; } newdata[size .. newsize] = 0; @@ -371,7 +371,7 @@ } else { - newdata = cast(byte *)_gc.calloc(newsize, 1); + newdata = cast(byte *)_gc.calloc(newsize + 1, 1); } } else @@ -408,9 +408,9 @@ if (newsize > size) { uint cap = _gc.capacity(p.data); - if (cap < newsize) + if (cap <= newsize) { - newdata = cast(byte *)_gc.malloc(newsize); + newdata = cast(byte *)_gc.malloc(newsize + 1); newdata[0 .. size] = p.data[0 .. size]; } newdata[size .. newsize] = 0; @@ -418,7 +418,7 @@ } else { - newdata = cast(byte *)_gc.calloc(newsize, 1); + newdata = cast(byte *)_gc.calloc(newsize + 1, 1); } } else @@ -447,7 +447,7 @@ { byte* newdata; //newdata = cast(byte *)_gc.malloc(newlength * size); - newdata = cast(byte *)_gc.malloc(newCapacity(newlength, size)); + newdata = cast(byte *)_gc.malloc(newCapacity(newlength, size) + 1); memcpy(newdata, px.data, length * size); px.data = newdata; } @@ -468,7 +468,7 @@ { void* newdata; //newdata = _gc.malloc(newlength * size); - newdata = _gc.malloc(newCapacity(newsize, 1)); + newdata = _gc.malloc(newCapacity(newsize, 1) + 1); memcpy(newdata, px.data, (length + 7) / 8); px.data = cast(byte*)newdata; } @@ -492,7 +492,7 @@ { version(none) { - newcap = newlength * size; + uint newcap = newlength * size; } else { @@ -543,6 +543,7 @@ //printf("mult: %2.2f, mult2: %2.2f, alloc: %2.2f\n",mult/100.0,mult2,newext / cast(double)size); } newcap = newext > newcap ? newext : newcap; + //printf("newcap = %d, newlength = %d, size = %d\n", newcap, newlength, size); } return newcap; } @@ -553,11 +554,18 @@ size_t cap = _gc.capacity(x); size_t length = x.length; size_t newlength = length + 1; - if (newlength * size > cap) + + assert(cap == 0 || length * size <= cap); + + //printf("_d_arrayappendc(size = %d, ptr = %p, length = %d, cap = %d)\n", size, x.ptr, x.length, cap); + + if (newlength * size >= cap) { byte* newdata; - //printf("_d_arrayappendc(%d, %d)\n", size, newlength); - newdata = cast(byte *)_gc.malloc(newCapacity(newlength, size)); + //printf("_d_arrayappendc(size = %d, newlength = %d, cap = %d)\n", size, newlength, cap); + cap = newCapacity(newlength, size); + assert(cap >= newlength * size); + newdata = cast(byte *)_gc.malloc(cap + 1); memcpy(newdata, x, length * size); (cast(void **)(&x))[1] = newdata; } @@ -565,29 +573,46 @@ *cast(size_t *)&x = newlength; (cast(byte *)x)[length * size .. newlength * size] = argp[0 .. size]; + assert((cast(uint)x.ptr & 15) == 0); + assert(_gc.capacity(x.ptr) > x.length * size); return x; +} -/+ - byte[] a; - uint length; - void *argp; +extern (C) +byte[] _d_arraycat(byte[] x, byte[] y, uint size) +out (result) +{ + //printf("_d_arraycat(%d,%p ~ %d,%p size = %d => %d,%p)\n", x.length, x.ptr, y.length, y.ptr, size, result.length, result.ptr); + assert(result.length == x.length + y.length); + for (uint i = 0; i < x.length * size; i++) + assert((cast(byte*)result)[i] == (cast(byte*)x)[i]); + for (uint i = 0; i < y.length * size; i++) + assert((cast(byte*)result)[x.length * size + i] == (cast(byte*)y)[i]); + + uint cap = _gc.capacity(result.ptr); + assert(!cap || cap > result.length * size); +} +body +{ byte[] a; + uint len; + + if (!y.length) + return x; + if (!x.length) + return y; - //printf("size = %d\n", size); - length = x.length + 1; - a = new byte[length * size]; + len = x.length + y.length; + a = new byte[len * size]; memcpy(a, x, x.length * size); - argp = &size + 1; - //printf("*argp = %llx\n", *cast(long *)argp); - memcpy(&a[x.length * size], argp, size); - //printf("a[0] = %llx\n", *cast(long *)&a[0]); - *cast(int *)&a = length; // jam length - //printf("a[0] = %llx\n", *cast(long *)&a[0]); - x = a; + //a[0 .. x.length * size] = x[]; + memcpy(&a[x.length * size], y, y.length * size); + *cast(int *)&a = len; // jam length + //a.length = len; return a; -+/ } + extern (C) bit[] _d_arrayappendcb(inout bit[] x, bit b) { diff -uNr dmd-0.121/dmd/src/phobos/std/c/stdlib.d dmd-0.122/dmd/src/phobos/std/c/stdlib.d --- dmd-0.121/dmd/src/phobos/std/c/stdlib.d 2005-04-15 14:30:48.000000000 +0200 +++ dmd-0.122/dmd/src/phobos/std/c/stdlib.d 2005-05-04 12:26:36.000000000 +0200 @@ -49,9 +49,12 @@ int getErrno(); int setErrno(int); +const int ERANGE = 34; // on both Windows and linux + double atof(char *); int atoi(char *); int atol(char *); +float strtof(char *,char **); double strtod(char *,char **); real strtold(char *,char **); long strtol(char *,char **,int); diff -uNr dmd-0.121/dmd/src/phobos/std/conv.d dmd-0.122/dmd/src/phobos/std/conv.d --- dmd-0.121/dmd/src/phobos/std/conv.d 2005-04-15 14:30:46.000000000 +0200 +++ dmd-0.122/dmd/src/phobos/std/conv.d 2005-05-04 12:26:36.000000000 +0200 @@ -3,15 +3,20 @@ // Copyright (c) 2002-2003 Digital Mars // All Rights Reserved // www.digitalmars.com +// Some parts contributed by David L. Davis // Conversion building blocks. These differ from the C equivalents by // checking for overflow and not allowing whitespace. module std.conv; -//debug=conv; // uncomment to turn on debugging printf's +private import std.string; // for atof(), toString() +private import std.c.stdlib; +private import std.math; // for fabs(), isnan() +private import std.stdio; // for writefln() and printf() +//debug=conv; // uncomment to turn on debugging printf's /************** Exceptions ****************/ @@ -831,4 +836,715 @@ } +/*************************************************************** + * Convert character string to float. + */ + +float toFloat(in char[] s) +{ + float f; + char* endptr; + char* sz; + + //writefln("toFloat('%s')", s); + sz = toStringz(s); + if (std.ctype.isspace(*sz)) + goto Lerr; + + // BUG: should set __locale_decpoint to "." for DMC + + setErrno(0); + f = strtof(sz, &endptr); + if (getErrno() == ERANGE) + goto Lerr; + if (endptr && (endptr == s || *endptr != 0)) + goto Lerr; + + return f; + + Lerr: + conv_error(s ~ " not representable as a float"); +} + +unittest +{ + debug( conv ) writefln( "conv.toFloat.unittest" ); + float f; + + f = toFloat( "123" ); + assert( f == 123f ); + f = toFloat( "+123" ); + assert( f == +123f ); + f = toFloat( "-123" ); + assert( f == -123f ); + f = toFloat( "123e+2" ); + assert( f == 123e+2f ); + + f = toFloat( "123e-2" ); + assert( f == 123e-2f ); + f = toFloat( "123." ); + assert( f == 123.f ); + f = toFloat( ".456" ); + assert( f == .456f ); + + // min and max + f = toFloat("1.17549e-38"); + assert(feq(cast(real)f, cast(real)1.17549e-38)); + assert(feq(cast(real)f, cast(real)float.min)); + f = toFloat("3.40282e+38"); + assert(toString(f) == toString(3.40282e+38)); + + // nan + f = toFloat("nan"); + assert(toString(f) == toString(float.nan)); +} + +/*************************************************************** + * Convert character string to double. + */ + +double toDouble(in char[] s) +{ + double f; + char* endptr; + char* sz; + + //writefln("toDouble('%s')", s); + sz = toStringz(s); + if (std.ctype.isspace(*sz)) + goto Lerr; + + // BUG: should set __locale_decpoint to "." for DMC + + setErrno(0); + f = strtod(sz, &endptr); + if (getErrno() == ERANGE) + goto Lerr; + if (endptr && (endptr == s || *endptr != 0)) + goto Lerr; + + return f; + + Lerr: + conv_error(s ~ " not representable as a double"); +} + +unittest +{ + debug( conv ) writefln( "conv.toDouble.unittest" ); + double d; + + d = toDouble( "123" ); + assert( d == 123 ); + d = toDouble( "+123" ); + assert( d == +123 ); + d = toDouble( "-123" ); + assert( d == -123 ); + d = toDouble( "123e2" ); + assert( d == 123e2); + d = toDouble( "123e-2" ); + assert( d == 123e-2 ); + d = toDouble( "123." ); + assert( d == 123. ); + d = toDouble( ".456" ); + assert( d == .456 ); + d = toDouble( "1.23456E+2" ); + assert( d == 1.23456E+2 ); + + // min and max + d = toDouble("2.22507e-308"); + assert(feq(cast(real)d, cast(real)2.22507e-308)); + assert(feq(cast(real)d, cast(real)double.min)); + d = toDouble("1.79769e+308"); + assert(toString(d) == toString(1.79769e+308)); + assert(toString(d) == toString(double.max)); + + // nan + d = toDouble("nan"); + assert(toString(d) == toString(double.nan)); + //assert(cast(real)d == cast(real)double.nan); +} + +/*************************************************************** + * Convert character string to real. + * Grammar: + * ['+'|'-'] digit {digit} + */ +real toReal(in char[] s) +{ + real f; + char* endptr; + char* sz; + + //writefln("toReal('%s')", s); + sz = toStringz(s); + if (std.ctype.isspace(*sz)) + goto Lerr; + + // BUG: should set __locale_decpoint to "." for DMC + + setErrno(0); + f = strtold(sz, &endptr); + if (getErrno() == ERANGE) + goto Lerr; + if (endptr && (endptr == s || *endptr != 0)) + goto Lerr; + + return f; + + Lerr: + conv_error(s ~ " not representable as a real"); +} + +unittest +{ + debug(conv) writefln("conv.toReal.unittest"); + real r; + + r = toReal("123"); + assert(r == 123L); + r = toReal("+123"); + assert(r == 123L); + r = toReal("-123"); + assert(r == -123L); + r = toReal("123e2"); + assert(feq(r, 123e2L)); + r = toReal("123e-2"); + assert(feq(r, 1.23L)); + r = toReal("123."); + assert(r == 123L); + r = toReal(".456"); + assert(r == .456L); + + r = toReal("1.23456e+2"); + assert(feq(r, 1.23456e+2L)); + r = toReal(toString(real.max / 2L)); + assert(toString(r) == toString(real.max / 2L)); + + // min and max + r = toReal(toString(real.min)); + assert(toString(r) == toString(real.min)); + r = toReal(toString(real.max)); + assert(toString(r) == toString(real.max)); + + // nan + r = toReal("nan"); + assert(toString(r) == toString(real.nan)); + //assert(r == real.nan); + + r = toReal(toString(real.nan)); + assert(toString(r) == toString(real.nan)); + //assert(r == real.nan); +} + +version (none) +{ /* These are removed for the moment because of concern about + * what to do about the 'i' suffix. Should it be there? + * Should it not? What about 'nan', should it be 'nani'? + * 'infinity' or 'infinityi'? + * Should it match what toString(ifloat) does with the 'i' suffix? + */ + +/*************************************************************** + * Convert character string to ifloat. + */ + +ifloat toIfloat(in char[] s) +{ + return toFloat(s) * 1.0i; +} + +unittest +{ + debug(conv) writefln("conv.toIfloat.unittest"); + ifloat ift; + + ift = toIfloat(toString(123.45)); + assert(toString(ift) == toString(123.45i)); + + ift = toIfloat(toString(456.77i)); + assert(toString(ift) == toString(456.77i)); + + // min and max + ift = toIfloat(toString(ifloat.min)); + assert(toString(ift) == toString(ifloat.min) ); + assert(feq(cast(ireal)ift, cast(ireal)ifloat.min)); + + ift = toIfloat(toString(ifloat.max)); + assert(toString(ift) == toString(ifloat.max)); + assert(feq(cast(ireal)ift, cast(ireal)ifloat.max)); + + // nan + ift = toIfloat("nani"); + assert(cast(real)ift == cast(real)ifloat.nan); + + ift = toIfloat(toString(ifloat.nan)); + assert(toString(ift) == toString(ifloat.nan)); + assert(feq(cast(ireal)ift, cast(ireal)ifloat.nan)); +} + +/*************************************************************** + * Convert character string to idouble. + */ + +idouble toIdouble(in char[] s) +{ + return toDouble(s) * 1.0i; +} + +unittest +{ + debug(conv) writefln("conv.toIdouble.unittest"); + idouble id; + + id = toIdouble(toString("123.45")); + assert(id == 123.45i); + + id = toIdouble(toString("123.45e+302i")); + assert(id == 123.45e+302i); + + // min and max + id = toIdouble(toString(idouble.min)); + assert(toString( id ) == toString(idouble.min)); + assert(feq(cast(ireal)id.re, cast(ireal)idouble.min.re)); + assert(feq(cast(ireal)id.im, cast(ireal)idouble.min.im)); + + id = toIdouble(toString(idouble.max)); + assert(toString(id) == toString(idouble.max)); + assert(feq(cast(ireal)id.re, cast(ireal)idouble.max.re)); + assert(feq(cast(ireal)id.im, cast(ireal)idouble.max.im)); + + // nan + id = toIdouble("nani"); + assert(cast(real)id == cast(real)idouble.nan); + + id = toIdouble(toString(idouble.nan)); + assert(toString(id) == toString(idouble.nan)); +} + +/*************************************************************** + * Convert character string to ireal. + */ + +ireal toIreal(in char[] s) +{ + return toReal(s) * 1.0i; +} + +unittest +{ + debug(conv) writefln("conv.toIreal.unittest"); + ireal ir; + + ir = toIreal(toString("123.45")); + assert(feq(cast(real)ir.re, cast(real)123.45i)); + + ir = toIreal(toString("123.45e+82i")); + assert(toString(ir) == toString(123.45e+82i)); + //assert(ir == 123.45e+82i); + + // min and max + ir = toIreal(toString(ireal.min)); + assert(toString(ir) == toString(ireal.min)); + assert(feq(cast(real)ir.re, cast(real)ireal.min.re)); + assert(feq(cast(real)ir.im, cast(real)ireal.min.im)); + + ir = toIreal(toString(ireal.max)); + assert(toString(ir) == toString(ireal.max)); + assert(feq(cast(real)ir.re, cast(real)ireal.max.re)); + //assert(feq(cast(real)ir.im, cast(real)ireal.max.im)); + + // nan + ir = toIreal("nani"); + assert(cast(real)ir == cast(real)ireal.nan); + + ir = toIreal(toString(ireal.nan)); + assert(toString(ir) == toString(ireal.nan)); +} + +/*************************************************************** + * Convert character string to cfloat. + * Grammar: + * ['+'|'-'] digit {digit} + */ +cfloat toCfloat(in char[] s) +{ + char[] s1; + char[] s2; + real r1; + real r2; + cfloat cf; + bit b = 0; + char* endptr; + + if (!s.length) + goto Lerr; + + b = getComplexStrings(s, s1, s2); + + if (!b) + goto Lerr; + + // atof(s1); + endptr = &s1[s1.length - 1]; + r1 = strtold(s1, &endptr); + + // atof(s2); + endptr = &s2[s2.length - 1]; + r2 = strtold(s2, &endptr); + + cf = cast(cfloat)(r1 + (r2 * 1.0i)); + + //writefln( "toCfloat() r1=%g, r2=%g, cf=%g, max=%g", + // r1, r2, cf, cfloat.max); + // Currently disabled due to a posted bug where a + // complex float greater-than compare to .max compares + // incorrectly. + //if (cf > cfloat.max) + // goto Loverflow; + + return cf; + + Loverflow: + conv_overflow(s); + + Lerr: + conv_error(s); + return cast(cfloat)0.0e-0+0i; +} + +unittest +{ + debug(conv) writefln("conv.toCfloat.unittest"); + cfloat cf; + + cf = toCfloat(toString("1.2345e-5+0i")); + assert(toString(cf) == toString(1.2345e-5+0i)); + assert(feq(cf, 1.2345e-5+0i)); + + // min and max + cf = toCfloat(toString(cfloat.min)); + assert(toString(cf) == toString(cfloat.min)); + + cf = toCfloat(toString(cfloat.max)); + assert(toString(cf) == toString(cfloat.max)); + + // nan ( nan+nani ) + cf = toCfloat("nani"); + //writefln("toCfloat() cf=%g, cf=\"%s\", nan=%s", + // cf, toString(cf), toString(cfloat.nan)); + assert(toString(cf) == toString(cfloat.nan)); + + cf = toCdouble("nan+nani"); + assert(toString(cf) == toString(cfloat.nan)); + + cf = toCfloat(toString(cfloat.nan)); + assert(toString(cf) == toString(cfloat.nan)); + assert(feq(cast(creal)cf, cast(creal)cfloat.nan)); +} + +/*************************************************************** + * Convert character string to cdouble. + * Grammar: + * ['+'|'-'] digit {digit} + */ +cdouble toCdouble(in char[] s) +{ + char[] s1; + char[] s2; + real r1; + real r2; + cdouble cd; + bit b = 0; + char* endptr; + + if (!s.length) + goto Lerr; + + b = getComplexStrings(s, s1, s2); + + if (!b) + goto Lerr; + + // atof(s1); + endptr = &s1[s1.length - 1]; + r1 = strtold(s1, &endptr); + + // atof(s2); + endptr = &s2[s2.length - 1]; + r2 = strtold(s2, &endptr); //atof(s2); + + cd = cast(cdouble)(r1 + (r2 * 1.0i)); + + //Disabled, waiting on a bug fix. + //if (cd > cdouble.max) //same problem the toCfloat() having + // goto Loverflow; + + return cd; + + Loverflow: + conv_overflow(s); + + Lerr: + conv_error(s); + return cast(cdouble)0.0e-0+0i; +} + +unittest +{ + debug(conv) writefln("conv.toCdouble.unittest"); + cdouble cd; + + cd = toCdouble(toString("1.2345e-5+0i")); + assert(toString( cd ) == toString(1.2345e-5+0i)); + assert(feq(cd, 1.2345e-5+0i)); + + // min and max + cd = toCdouble(toString(cdouble.min)); + assert(toString(cd) == toString(cdouble.min)); + assert(feq(cast(creal)cd, cast(creal)cdouble.min)); + + cd = toCdouble(toString(cdouble.max)); + assert(toString( cd ) == toString(cdouble.max)); + assert(feq(cast(creal)cd, cast(creal)cdouble.max)); + + // nan ( nan+nani ) + cd = toCdouble("nani"); + assert(toString(cd) == toString(cdouble.nan)); + + cd = toCdouble("nan+nani"); + assert(toString(cd) == toString(cdouble.nan)); + + cd = toCdouble(toString(cdouble.nan)); + assert(toString(cd) == toString(cdouble.nan)); + assert(feq(cast(creal)cd, cast(creal)cdouble.nan)); +} + +/*************************************************************** + * Convert character string to creal. + * Grammar: + * ['+'|'-'] digit {digit} + */ +creal toCreal(in char[] s) +{ + char[] s1; + char[] s2; + real r1; + real r2; + creal cr; + bit b = 0; + char* endptr; + + if (!s.length) + goto Lerr; + + b = getComplexStrings(s, s1, s2); + + if (!b) + goto Lerr; + + // atof(s1); + endptr = &s1[s1.length - 1]; + r1 = strtold(s1, &endptr); + + // atof(s2); + endptr = &s2[s2.length - 1]; + r2 = strtold(s2, &endptr); //atof(s2); + + //writefln("toCreal() r1=%g, r2=%g, s1=\"%s\", s2=\"%s\", nan=%g", + // r1, r2, s1, s2, creal.nan); + + if (s1 =="nan" && s2 == "nani") + cr = creal.nan; + else if (r2 != 0.0) + cr = cast(creal)(r1 + (r2 * 1.0i)); + else + cr = cast(creal)(r1 + 0.0i); + + return cr; + + Lerr: + conv_error(s); + return cast(creal)0.0e-0+0i; +} + +unittest +{ + debug(conv) writefln("conv.toCreal.unittest"); + creal cr; + + cr = toCreal(toString("1.2345e-5+0i")); + assert(toString(cr) == toString(1.2345e-5+0i)); + assert(feq(cr, 1.2345e-5+0i)); + + cr = toCreal(toString("0.0e-0+0i")); + assert(toString(cr) == toString(0.0e-0+0i)); + assert(cr == 0.0e-0+0i); + assert(feq(cr, 0.0e-0+0i)); + + cr = toCreal("123"); + assert(cr == 123); + + cr = toCreal("+5"); + assert(cr == 5); + + cr = toCreal("-78"); + assert(cr == -78); + + // min and max + cr = toCreal(toString(creal.min)); + assert(toString(cr) == toString(creal.min)); + assert(feq(cr, creal.min)); + + cr = toCreal(toString(creal.max)); + assert(toString(cr) == toString(creal.max)); + assert(feq(cr, creal.max)); + + // nan ( nan+nani ) + cr = toCreal("nani"); + assert(toString(cr) == toString(creal.nan)); + + cr = toCreal("nan+nani"); + assert(toString(cr) == toString(creal.nan)); + + cr = toCreal(toString(cdouble.nan)); + assert(toString(cr) == toString(creal.nan)); + assert(feq(cr, creal.nan)); +} + +} + +/*************************************************************** + * Splits a complex float (cfloat, cdouble, and creal) into two workable strings. + * Grammar: + * ['+'|'-'] string floating-point digit {digit} + */ +private bit getComplexStrings(in char[] s, out char[] s1, out char[] s2) +{ + int len = s.length; + + if (!len) + goto Lerr; + + // When "nan" or "nani" just return them. + if (s == "nan" || s == "nani" || s == "nan+nani") + { + s1 = "nan"; + s2 = "nani"; + return 1; + } + + // Split the original string out into two strings. + for (int i = 1; i < len; i++) + if ((s[i - 1] != 'e' && s[i - 1] != 'E') && s[i] == '+') + { + s1 = s[0..i]; + if (i + 1 < len - 1) + s2 = s[i + 1..len - 1]; + else + s2 = "0e+0i"; + + break; + } + + // Handle the case when there's only a single value + // to work with, and set the other string to zero. + if (!s1.length) + { + s1 = s; + s2 = "0e+0i"; + } + + //writefln( "getComplexStrings() s=\"%s\", s1=\"%s\", s2=\"%s\", len=%d", + // s, s1, s2, len ); + + return 1; + + Lerr: + // Display the original string in the error message. + conv_error("getComplexStrings() \"" ~ s ~ "\"" ~ " s1=\"" ~ s1 ~ "\"" ~ " s2=\"" ~ s2 ~ "\""); + return 0; +} + +// feq() functions now used only in unittesting + +/**************************************** + * Main function to compare reals with given precision + */ +private bit feq(in real rx, in real ry, in real precision) +{ + if (rx == ry) + return 1; + + if (isnan(rx)) + return cast(bit)isnan(ry); + + if (isnan(ry)) + return 0; + + return cast(bit)(fabs(rx - ry) <= precision); +} + +/**************************************** + * (Note: Copied here from std.math's mfeq() function for unittesting) + * Simple function to compare two floating point values + * to a specified precision. + * Returns: + * 1 match + * 0 nomatch + */ +private bit feq(in real r1, in real r2) +{ + if (r1 == r2) + return 1; + + if (isnan(r1)) + return cast(bit)isnan(r2); + + if (isnan(r2)) + return 0; + + return cast(bit)(feq(r1, r2, 0.000001L)); +} + +/**************************************** + * compare ireals with given precision + */ +private bit feq(in ireal r1, in ireal r2) +{ + real rx = cast(real)r1; + real ry = cast(real)r2; + + if (rx == ry) + return 1; + + if (isnan(rx)) + return cast(bit)isnan(ry); + + if (isnan(ry)) + return 0; + + return feq(rx, ry, 0.000001L); +} + +/**************************************** + * compare creals with given precision + */ +private bit feq(in creal r1, in creal r2) +{ + real r1a = fabs(cast(real)r1.re - cast(real)r2.re); + real r2b = fabs(cast(real)r1.im - cast(real)r2.im); + + if ((cast(real)r1.re == cast(real)r2.re) && + (cast(real)r1.im == cast(real)r2.im)) + return 1; + + if (isnan(r1a)) + return cast(bit)isnan(r2b); + + if (isnan(r2b)) + return 0; + + return feq(r1a, r2b, 0.000001L); +} diff -uNr dmd-0.121/dmd/src/phobos/std/stream.d dmd-0.122/dmd/src/phobos/std/stream.d --- dmd-0.121/dmd/src/phobos/std/stream.d 2005-04-15 14:30:48.000000000 +0200 +++ dmd-0.122/dmd/src/phobos/std/stream.d 2005-05-04 12:26:36.000000000 +0200 @@ -213,13 +213,13 @@ // writes a line, throws WriteException on error void writeLine(char[] s); - // writes a UNICODE line, throws WriteException on error + // writes a Unicode line, throws WriteException on error void writeLineW(wchar[] s); // writes a string, throws WriteException on error void writeString(char[] s); - // writes a UNICODE string, throws WriteException on error + // writes a Unicode string, throws WriteException on error void writeStringW(wchar[] s); // writes data to stream using vprintf() syntax, @@ -248,17 +248,27 @@ bit seekable = false; protected bit isopen = true; + // flag that last readBlock resulted in eof + protected bit readEOF = false; + this() {} // reads block of data of specified size, // returns actual number of bytes read + // returning 0 indicates end-of-file abstract size_t readBlock(void* buffer, size_t size); // reads block of data of specified size, // throws ReadException on error void readExact(void* buffer, size_t size) { - size_t readsize = readBlock(buffer, size); - if (readsize != size) + for(;;) { + if (!size) return; + size_t readsize = readBlock(buffer, size); // return 0 on eof + if (readsize == 0) break; + buffer += readsize; + size -= readsize; + } + if (size != 0) throw new ReadException("not enough data in stream"); } @@ -465,6 +475,7 @@ // unget buffer private wchar[] unget; + final int ungetAvailable() { return unget.length > 1; } // reads and returns next character from the stream, // handles characters pushed back by ungetc() @@ -876,7 +887,7 @@ writeString("\n"); } - // writes a UNICODE line, throws WriteException on error + // writes a Unicode line, throws WriteException on error void writeLineW(wchar[] s) { writeStringW(s); version (Win32) @@ -892,7 +903,7 @@ writeExact(s, s.length); } - // writes a UNICODE string, throws WriteException on error + // writes a Unicode string, throws WriteException on error void writeStringW(wchar[] s) { writeExact(s, s.length * wchar.sizeof); } @@ -962,10 +973,18 @@ // copies all data from given stream into this one, // may throw ReadException or WriteException on failure void copyFrom(Stream s) { - ulong pos = s.position(); - s.position(0); - copyFrom(s, s.size()); - s.position(pos); + if (seekable) { + ulong pos = s.position(); + s.position(0); + copyFrom(s, s.size()); + s.position(pos); + } else { + ubyte[128] buf; + while (!s.eof()) { + size_t m = s.readBlock(buf, buf.length); + writeExact(buf, m); + } + } } // copies specified number of bytes from given stream into @@ -1001,16 +1020,25 @@ // returns size of stream ulong size() { + assertSeekable(); ulong pos = position(), result = seek(0, SeekPos.End); position(pos); return result; } // returns true if end of stream is reached, false otherwise - bit eof() { return position() == size(); } + bit eof() { + // for unseekable streams we only know the end when we read it + if (readEOF && !ungetAvailable()) + return true; + else if (seekable) + return position() == size(); + else + return false; + } // returns true if the stream is open - bit isOpen() { return isopen; } + bool isOpen() { return isopen; } // flush the buffer if writeable void flush() { @@ -1022,7 +1050,7 @@ void close() { if (isopen) flush(); - isopen = readable = writeable = seekable = false; + readEOF = isopen = readable = writeable = seekable = false; } // creates a string in memory containing copy of stream data @@ -1049,8 +1077,8 @@ result = new char[blockSize]; while ((rdlen = readBlock(&result[pos], blockSize)) > 0) { pos += rdlen; - result.length = result.length + blockSize; blockSize += rdlen; + result.length = result.length + blockSize; } } return result[0 .. pos]; @@ -1063,7 +1091,8 @@ ulong pos = position(); uint crc = init_crc32 (); position(0); - for (ulong i = 0; i < size(); i++) { + ulong len = size(); + for (ulong i = 0; i < len; i++) { ubyte c; read(c); crc = update_crc32(c, crc); @@ -1135,6 +1164,7 @@ readable = writeable = seekable = false; isopen = false; } + readEOF = false; streamPos = 0; bufferLen = bufferSourcePos = bufferCurPos = 0; bufferDirty = false; @@ -1151,45 +1181,49 @@ // reads block of data of specified size using any buffered data // returns actual number of bytes read - override size_t readBlock(void* result, size_t size) { + override size_t readBlock(void* result, size_t len) { + if (len == 0) return 0; + assertReadable(); - ubyte* buf = cast(ubyte*)result; + ubyte* outbuf = cast(ubyte*)result; size_t readsize = 0; - if (bufferCurPos + size <= bufferLen) { + if (bufferCurPos + len < bufferLen) { // buffer has all the data so copy it - buf[0 .. size] = buffer[bufferCurPos .. bufferCurPos+size]; - bufferCurPos += size; - readsize = size; + outbuf[0 .. len] = buffer[bufferCurPos .. bufferCurPos+len]; + bufferCurPos += len; + readsize = len; goto ExitRead; } readsize = bufferLen - bufferCurPos; if (readsize > 0) { // buffer has some data so copy what is left - buf[0 .. readsize] = buffer[bufferCurPos .. bufferLen]; - buf += readsize; + outbuf[0 .. readsize] = buffer[bufferCurPos .. bufferLen]; + outbuf += readsize; bufferCurPos += readsize; - size -= readsize; + len -= readsize; } flush(); - if (size >= buffer.length) { + if (len >= buffer.length) { // buffer can't hold the data so fill output buffer directly - size_t siz = s.readBlock(buf, size); + size_t siz = s.readBlock(outbuf, len); readsize += siz; streamPos += siz; + readEOF = siz == 0; } else { // read a new block into buffer bufferLen = s.readBlock(buffer, buffer.length); - if (bufferLen < size) size = bufferLen; - buf[0 .. size] = buffer[0 .. size]; + readEOF = bufferLen == 0; + if (bufferLen < len) len = bufferLen; + outbuf[0 .. len] = buffer[0 .. len]; bufferSourcePos = bufferLen; streamPos += bufferLen; - bufferCurPos = size; - readsize += size; + bufferCurPos = len; + readsize += len; } ExitRead: @@ -1198,7 +1232,7 @@ // write block of data of specified size // returns actual number of bytes written - override size_t writeBlock(void* result, size_t size) { + override size_t writeBlock(void* result, size_t len) { assertWriteable(); ubyte* buf = cast(ubyte*)result; @@ -1206,26 +1240,26 @@ if (bufferLen == 0) { // buffer is empty so fill it if possible - if ((size < buffer.length) && (readable)) { + if ((len < buffer.length) && (readable)) { // read in data if the buffer is currently empty bufferLen = s.readBlock(buffer,buffer.length); bufferSourcePos = bufferLen; streamPos += bufferLen; - } else if (size >= buffer.length) { + } else if (len >= buffer.length) { // buffer can't hold the data so write it directly and exit - writesize = s.writeBlock(buf,size); + writesize = s.writeBlock(buf,len); streamPos += writesize; goto ExitWrite; } } - if (bufferCurPos + size <= buffer.length) { + if (bufferCurPos + len <= buffer.length) { // buffer has space for all the data so copy it and exit - buffer[bufferCurPos .. bufferCurPos+size] = buf[0 .. size]; - bufferCurPos += size; + buffer[bufferCurPos .. bufferCurPos+len] = buf[0 .. len]; + bufferCurPos += len; bufferLen = bufferCurPos > bufferLen ? bufferCurPos : bufferLen; - writesize = size; + writesize = len; bufferDirty = true; goto ExitWrite; } @@ -1236,7 +1270,7 @@ buffer[bufferCurPos .. buffer.length] = buf[0 .. writesize]; bufferCurPos = bufferLen = buffer.length; buf += writesize; - size -= writesize; + len -= writesize; bufferDirty = true; } @@ -1245,7 +1279,7 @@ flush(); - writesize += writeBlock(buf,size); + writesize += writeBlock(buf,len); ExitWrite: return writesize; @@ -1262,6 +1296,7 @@ } else { bufferCurPos += offset; } + readEOF = false; return streamPos-bufferSourcePos+bufferCurPos; } @@ -1318,7 +1353,7 @@ } // template TreadLine(T) override char[] readLine(char[] inBuffer) { - if (unget.length > 1) + if (ungetAvailable()) return super.readLine(inBuffer); else return TreadLine!(char).readLine(inBuffer); @@ -1326,7 +1361,7 @@ alias Stream.readLine readLine; override wchar[] readLineW(wchar[] inBuffer) { - if (unget.length > 1) + if (ungetAvailable()) return super.readLineW(inBuffer); else return TreadLine!(wchar).readLine(inBuffer); @@ -1342,7 +1377,7 @@ body { super.flush(); if (writeable && bufferDirty) { - if (bufferSourcePos != 0) { + if (bufferSourcePos != 0 && seekable) { // move actual file pointer to front of buffer streamPos = s.seek(-bufferSourcePos, SeekPos.Current); } @@ -1353,7 +1388,7 @@ } } long diff = bufferCurPos-bufferSourcePos; - if (diff != 0) { + if (diff != 0 && seekable) { // move actual file pointer to current position streamPos = s.seek(diff, SeekPos.Current); } @@ -1363,23 +1398,21 @@ } // returns true if end of stream is reached, false otherwise - override bit eof() { + override bool eof() { if ((buffer.length == 0) || !readable) { return super.eof(); } - if (bufferCurPos == bufferLen) { - if ((bufferLen != buffer.length) && - (bufferLen != 0)) { - return true; - } - } - else + // some simple tests to avoid flushing + if (ungetAvailable() || bufferCurPos != bufferLen) return false; - size_t res = s.readBlock(buffer,buffer.length); - bufferSourcePos = bufferLen = res; + if (bufferLen == buffer.length) + flush(); + size_t res = s.readBlock(&buffer[bufferLen],buffer.length-bufferLen); + bufferSourcePos += res; + bufferLen += res; streamPos += res; - bufferCurPos = 0; - return res == 0; + readEOF = res == 0; + return readEOF; } // returns size of stream @@ -1572,6 +1605,7 @@ version (Win32) { // returns size of stream ulong size() { + assertSeekable(); uint sizehi; uint sizelow = GetFileSize(hFile,&sizehi); return (cast(ulong)sizehi << 32) + sizelow; @@ -1587,6 +1621,7 @@ if (size == -1) size = 0; } + readEOF = (size == 0); return size; } @@ -1615,6 +1650,7 @@ if (result == 0xFFFFFFFF) throw new SeekException("unable to move file pointer"); } + readEOF = false; return result; } @@ -1983,7 +2019,7 @@ } override void flush() { super.flush(); s.flush(); } - override bit eof() { return s.eof(); } + override bool eof() { return s.eof() && !ungetAvailable(); } override ulong size() { return s.size(); } unittest { diff -uNr dmd-0.121/dmd/src/phobos/std/string.d dmd-0.122/dmd/src/phobos/std/string.d --- dmd-0.121/dmd/src/phobos/std/string.d 2005-04-15 14:30:46.000000000 +0200 +++ dmd-0.122/dmd/src/phobos/std/string.d 2005-05-04 12:26:36.000000000 +0200 @@ -49,7 +49,6 @@ void *memmove(void *, void *, uint); void *memset(void *, uint, uint); char* strerror(int); - real strtold(char*, char**); int wcslen(wchar *); int wcscmp(wchar *, wchar *); diff -uNr dmd-0.121/dmd/src/phobos/std/typeinfo/ti_cdouble.d dmd-0.122/dmd/src/phobos/std/typeinfo/ti_cdouble.d --- dmd-0.121/dmd/src/phobos/std/typeinfo/ti_cdouble.d 2005-04-15 14:30:48.000000000 +0200 +++ dmd-0.122/dmd/src/phobos/std/typeinfo/ti_cdouble.d 2005-05-04 12:26:36.000000000 +0200 @@ -17,8 +17,19 @@ } static int _compare(cdouble f1, cdouble f2) - { - return f1 < f2 ? -1 : f1 > f2 ? 1 : 0; + { int result; + + if (f1.re < f2.re) + result = -1; + else if (f1.re > f2.re) + result = 1; + else if (f1.im < f2.im) + result = -1; + else if (f1.im > f2.im) + result = 1; + else + result = 0; + return result; } int equals(void *p1, void *p2) diff -uNr dmd-0.121/dmd/src/phobos/std/typeinfo/ti_cfloat.d dmd-0.122/dmd/src/phobos/std/typeinfo/ti_cfloat.d --- dmd-0.121/dmd/src/phobos/std/typeinfo/ti_cfloat.d 2005-04-15 14:30:48.000000000 +0200 +++ dmd-0.122/dmd/src/phobos/std/typeinfo/ti_cfloat.d 2005-05-04 12:26:36.000000000 +0200 @@ -16,8 +16,19 @@ } static int _compare(cfloat f1, cfloat f2) - { - return f1 < f2 ? -1 : f1 > f2 ? 1 : 0; + { int result; + + if (f1.re < f2.re) + result = -1; + else if (f1.re > f2.re) + result = 1; + else if (f1.im < f2.im) + result = -1; + else if (f1.im > f2.im) + result = 1; + else + result = 0; + return result; } int equals(void *p1, void *p2) diff -uNr dmd-0.121/dmd/src/phobos/std/typeinfo/ti_creal.d dmd-0.122/dmd/src/phobos/std/typeinfo/ti_creal.d --- dmd-0.121/dmd/src/phobos/std/typeinfo/ti_creal.d 2005-04-15 14:30:48.000000000 +0200 +++ dmd-0.122/dmd/src/phobos/std/typeinfo/ti_creal.d 2005-05-04 12:26:36.000000000 +0200 @@ -18,8 +18,19 @@ } static int _compare(creal f1, creal f2) - { - return f1 < f2 ? -1 : f1 > f2 ? 1 : 0; + { int result; + + if (f1.re < f2.re) + result = -1; + else if (f1.re > f2.re) + result = 1; + else if (f1.im < f2.im) + result = -1; + else if (f1.im > f2.im) + result = 1; + else + result = 0; + return result; } int equals(void *p1, void *p2) diff -uNr dmd-0.121/dmd/src/phobos/unittest.d dmd-0.122/dmd/src/phobos/unittest.d --- dmd-0.121/dmd/src/phobos/unittest.d 2005-04-15 14:30:46.000000000 +0200 +++ dmd-0.122/dmd/src/phobos/unittest.d 2005-05-04 12:26:36.000000000 +0200 @@ -43,6 +43,7 @@ import std.zlib; import std.md5; import std.stdio; +import std.conv; int main(char[][] args) { @@ -53,7 +54,8 @@ printf("test1\n"); fncharmatch('a', 'b'); // path isnan(1.0); // math - feq(1.0, 2.0); // math2 + std.math2.feq(1.0, 2.0); // math2 + std.conv.toDouble("1.0"); // std.conv printf("test1\n"); OutBuffer b = new OutBuffer(); // outbuffer std.ctype.tolower('A'); // ctype diff -uNr dmd-0.121/dmd/src/phobos/win32.mak dmd-0.122/dmd/src/phobos/win32.mak --- dmd-0.121/dmd/src/phobos/win32.mak 2005-04-15 14:30:46.000000000 +0200 +++ dmd-0.122/dmd/src/phobos/win32.mak 2005-05-04 12:26:34.000000000 +0200 @@ -65,6 +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 \ 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 \ @@ -363,6 +364,8 @@ make -f win32.mak zlib.lib cd ..\..\.. +errno.obj : errno.c + ### internal aaA.obj : internal\aaA.d