diff -uNr dmd-0.152/dmd/src/dmd/aggregate.h dmd-0.153/dmd/src/dmd/aggregate.h --- dmd-0.152/dmd/src/dmd/aggregate.h 2006-03-12 12:59:56.000000000 +0100 +++ dmd-0.153/dmd/src/dmd/aggregate.h 2006-04-09 12:19:50.000000000 +0200 @@ -153,6 +153,7 @@ struct ClassDeclaration : AggregateDeclaration { + static ClassDeclaration *object; static ClassDeclaration *classinfo; ClassDeclaration *baseClass; // NULL only if this is Object diff -uNr dmd-0.152/dmd/src/dmd/cast.c dmd-0.153/dmd/src/dmd/cast.c --- dmd-0.152/dmd/src/dmd/cast.c 2006-03-27 17:07:30.000000000 +0200 +++ dmd-0.153/dmd/src/dmd/cast.c 2006-04-06 02:01:46.000000000 +0200 @@ -473,6 +473,29 @@ return e; } + +Expression *RealExp::castTo(Type *t) +{ + if (type->isreal() && t->isreal()) + type = t; + else if (type->isimaginary() && t->isimaginary()) + type = t; + else + return Expression::castTo(t); + return this; +} + + +Expression *ComplexExp::castTo(Type *t) +{ + if (type->iscomplex() && t->iscomplex()) + type = t; + else + return Expression::castTo(t); + return this; +} + + Expression *NullExp::castTo(Type *t) { Expression *e; Type *tb; diff -uNr dmd-0.152/dmd/src/dmd/class.c dmd-0.153/dmd/src/dmd/class.c --- dmd-0.152/dmd/src/dmd/class.c 2006-03-27 16:46:00.000000000 +0200 +++ dmd-0.153/dmd/src/dmd/class.c 2006-04-09 22:32:04.000000000 +0200 @@ -29,10 +29,13 @@ /********************************* ClassDeclaration ****************************/ ClassDeclaration *ClassDeclaration::classinfo; +ClassDeclaration *ClassDeclaration::object; ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses) : AggregateDeclaration(loc, id) { + static char msg[] = "only object.d can define this reserved class name"; + if (baseclasses) this->baseclasses = *baseclasses; baseClass = NULL; @@ -56,52 +59,99 @@ vtblsym = NULL; vclassinfo = NULL; - if (id == Id::__sizeof || id == Id::alignof || id == Id::mangleof) - error("illegal class name"); + if (id) + { // Look for special class names - // BUG: What if this is the wrong ClassInfo, i.e. it is nested? - if (!classinfo && id == Id::ClassInfo) - classinfo = this; + if (id == Id::__sizeof || id == Id::alignof || id == Id::mangleof) + error("illegal class name"); - // BUG: What if this is the wrong ModuleInfo, i.e. it is nested? - if (!Module::moduleinfo && id == Id::ModuleInfo) - Module::moduleinfo = this; + // BUG: What if this is the wrong TypeInfo, i.e. it is nested? + if (id->toChars()[0] == 'T') + { + if (id == Id::TypeInfo) + { if (Type::typeinfo) + Type::typeinfo->error(msg); + Type::typeinfo = this; + } - // BUG: What if this is the wrong TypeInfo, i.e. it is nested? - if (id && id->toChars()[0] == 'T') - { - if (!Type::typeinfo && id == Id::TypeInfo) - Type::typeinfo = this; + if (id == Id::TypeInfo_Class) + { if (Type::typeinfoclass) + Type::typeinfoclass->error(msg); + Type::typeinfoclass = this; + } - if (!Type::typeinfoclass && id == Id::TypeInfo_Class) - Type::typeinfoclass = this; + if (id == Id::TypeInfo_Struct) + { if (Type::typeinfostruct) + Type::typeinfostruct->error(msg); + Type::typeinfostruct = this; + } - if (!Type::typeinfostruct && id == Id::TypeInfo_Struct) - Type::typeinfostruct = this; + if (id == Id::TypeInfo_Typedef) + { if (Type::typeinfotypedef) + Type::typeinfotypedef->error(msg); + Type::typeinfotypedef = this; + } - if (!Type::typeinfotypedef && id == Id::TypeInfo_Typedef) - Type::typeinfotypedef = this; + if (id == Id::TypeInfo_Pointer) + { if (Type::typeinfopointer) + Type::typeinfopointer->error(msg); + Type::typeinfopointer = this; + } - if (!Type::typeinfopointer && id == Id::TypeInfo_Pointer) - Type::typeinfopointer = this; + if (id == Id::TypeInfo_Array) + { if (Type::typeinfoarray) + Type::typeinfoarray->error(msg); + Type::typeinfoarray = this; + } - if (!Type::typeinfoarray && id == Id::TypeInfo_Array) - Type::typeinfoarray = this; + if (id == Id::TypeInfo_StaticArray) + { //if (Type::typeinfostaticarray) + //Type::typeinfostaticarray->error(msg); + Type::typeinfostaticarray = this; + } - if (!Type::typeinfostaticarray && id == Id::TypeInfo_StaticArray) - Type::typeinfostaticarray = this; + if (id == Id::TypeInfo_AssociativeArray) + { if (Type::typeinfoassociativearray) + Type::typeinfoassociativearray->error(msg); + Type::typeinfoassociativearray = this; + } - if (!Type::typeinfoassociativearray && id == Id::TypeInfo_AssociativeArray) - Type::typeinfoassociativearray = this; + if (id == Id::TypeInfo_Enum) + { if (Type::typeinfoenum) + Type::typeinfoenum->error(msg); + Type::typeinfoenum = this; + } - if (!Type::typeinfoenum && id == Id::TypeInfo_Enum) - Type::typeinfoenum = this; + if (id == Id::TypeInfo_Function) + { if (Type::typeinfofunction) + Type::typeinfofunction->error(msg); + Type::typeinfofunction = this; + } - if (!Type::typeinfofunction && id == Id::TypeInfo_Function) - Type::typeinfofunction = this; + if (id == Id::TypeInfo_Delegate) + { if (Type::typeinfodelegate) + Type::typeinfodelegate->error(msg); + Type::typeinfodelegate = this; + } + } - if (!Type::typeinfodelegate && id == Id::TypeInfo_Delegate) - Type::typeinfodelegate = this; + if (id == Id::Object) + { if (object) + object->error(msg); + object = this; + } + + if (id == Id::ClassInfo) + { if (classinfo) + classinfo->error(msg); + classinfo = this; + } + + if (id == Id::ModuleInfo) + { if (Module::moduleinfo) + Module::moduleinfo->error(msg); + Module::moduleinfo = this; + } } com = 0; @@ -280,6 +330,11 @@ TypeClass *tc; Type *bt; + if (!object) + { + error("missing or corrupt object.d"); + fatal(); + } bt = tbase->semantic(loc, sc)->toBasetype(); b = new BaseClass(bt, PROTpublic); baseclasses.shift(b); diff -uNr dmd-0.152/dmd/src/dmd/constfold.c dmd-0.153/dmd/src/dmd/constfold.c --- dmd-0.152/dmd/src/dmd/constfold.c 2006-04-03 01:18:42.000000000 +0200 +++ dmd-0.153/dmd/src/dmd/constfold.c 2006-04-10 13:42:32.000000000 +0200 @@ -110,6 +110,7 @@ Expression *CastExp::constFold() { //printf("CastExp::constFold(%s)\n", toChars()); + //printf("from %s to %s\n", type->toChars(), to->toChars()); //printf("type = %p\n", type); assert(type); diff -uNr dmd-0.152/dmd/src/dmd/expression.h dmd-0.153/dmd/src/dmd/expression.h --- dmd-0.152/dmd/src/dmd/expression.h 2006-03-07 19:44:50.000000000 +0100 +++ dmd-0.153/dmd/src/dmd/expression.h 2006-04-06 02:01:40.000000000 +0200 @@ -165,6 +165,7 @@ real_t toReal(); real_t toImaginary(); complex_t toComplex(); + Expression *castTo(Type *t); int isConst(); int isBool(int result); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -186,6 +187,7 @@ real_t toReal(); real_t toImaginary(); complex_t toComplex(); + Expression *castTo(Type *t); int isConst(); int isBool(int result); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); diff -uNr dmd-0.152/dmd/src/dmd/link.c dmd-0.153/dmd/src/dmd/link.c --- dmd-0.152/dmd/src/dmd/link.c 2006-03-22 10:57:58.000000000 +0100 +++ dmd-0.153/dmd/src/dmd/link.c 2006-04-08 02:05:24.000000000 +0200 @@ -191,6 +191,20 @@ argv.push((void *)"-lpthread"); argv.push((void *)"-lm"); + if (global.params.exefile) + { + /* This switch enables what is known as 'smart linking' + * in the Windows world, where unreferenced sections + * are removed from the executable. It eliminates unreferenced + * functions, essentially making a 'library' out of a module. + * Although it is documented to work with ld version 2.13, + * in practice it does not, but just seems to be ignored. + * Thomas Kuehne has verified that it works with ld 2.16.1. + */ + argv.push((void *)"-Xlinker"); + argv.push((void *)"--gc-sections"); + } + for (i = 0; i < global.params.linkswitches->dim; i++) { argv.push((void *)"-Xlinker"); diff -uNr dmd-0.152/dmd/src/dmd/macro.h dmd-0.153/dmd/src/dmd/macro.h --- dmd-0.152/dmd/src/dmd/macro.h 2005-09-21 19:31:14.000000000 +0200 +++ dmd-0.153/dmd/src/dmd/macro.h 2006-04-05 09:37:02.000000000 +0200 @@ -30,7 +30,7 @@ int inuse; // macro is in use (don't expand) Macro(unsigned char *name, size_t namelen, unsigned char *text, size_t textlen); - Macro *Macro::search(unsigned char *name, size_t namelen); + Macro *search(unsigned char *name, size_t namelen); public: static Macro *define(Macro **ptable, unsigned char *name, size_t namelen, unsigned char *text, size_t textlen); diff -uNr dmd-0.152/dmd/src/dmd/mangle.c dmd-0.153/dmd/src/dmd/mangle.c --- dmd-0.152/dmd/src/dmd/mangle.c 2006-02-15 00:16:38.000000000 +0100 +++ dmd-0.153/dmd/src/dmd/mangle.c 2006-04-09 12:22:50.000000000 +0200 @@ -148,9 +148,9 @@ ident == Id::TypeInfo_Class || ident == Id::TypeInfo_Typedef || ident == Id::Exception || - ident == Id::Object || - ident == Id::ClassInfo || - ident == Id::ModuleInfo || + this == object || + this == classinfo || + this == Module::moduleinfo || memcmp(ident->toChars(), "TypeInfo_", 9) == 0 ) parent = NULL; diff -uNr dmd-0.152/dmd/src/dmd/mars.c dmd-0.153/dmd/src/dmd/mars.c --- dmd-0.152/dmd/src/dmd/mars.c 2006-03-24 22:10:12.000000000 +0100 +++ dmd-0.153/dmd/src/dmd/mars.c 2006-04-06 21:16:52.000000000 +0200 @@ -58,7 +58,7 @@ copyright = "Copyright (c) 1999-2006 by Digital Mars"; written = "written by Walter Bright"; - version = "v0.151"; + version = "v0.153"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); @@ -154,6 +154,7 @@ -Ipath where to look for imports\n\ -inline do function inlining\n\ -Llinkerflag pass linkerflag to link\n\ + -nofloat do not emit reference to floating point\n\ -O optimize\n\ -o- do not write object file\n\ -odobjdir write object files to directory objdir\n\ @@ -356,6 +357,8 @@ #endif else if (strcmp(p + 1, "inline") == 0) global.params.useInline = 1; + else if (strcmp(p + 1, "nofloat") == 0) + global.params.nofloat = 1; else if (strcmp(p + 1, "quiet") == 0) global.params.quiet = 1; else if (strcmp(p + 1, "release") == 0) diff -uNr dmd-0.152/dmd/src/dmd/mars.h dmd-0.153/dmd/src/dmd/mars.h --- dmd-0.152/dmd/src/dmd/mars.h 2006-02-20 21:18:26.000000000 +0100 +++ dmd-0.153/dmd/src/dmd/mars.h 2006-04-06 21:15:42.000000000 +0200 @@ -48,6 +48,7 @@ char warnings; // enable warnings char pic; // generate position-independent-code for shared libs char cov; // generate code coverage data + char nofloat; // code should not pull in floating point support char *argv0; // program name Array *imppath; // array of char*'s of where to look for import modules diff -uNr dmd-0.152/dmd/src/dmd/optimize.c dmd-0.153/dmd/src/dmd/optimize.c --- dmd-0.152/dmd/src/dmd/optimize.c 2006-01-29 14:26:30.000000000 +0100 +++ dmd-0.153/dmd/src/dmd/optimize.c 2006-04-09 15:37:52.000000000 +0200 @@ -195,9 +195,10 @@ Expression *CommaExp::optimize(int result) { Expression *e; + //printf("CommaExp::optimize(result = %d) %s\n", result, toChars()); e1 = e1->optimize(0); e2 = e2->optimize(result); - if (!e1) + if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64) { e = e2; if (e) @@ -334,7 +335,11 @@ e1 = e1->optimize(WANTflags); e = this; if (e1->isBool(FALSE)) - e = new IntegerExp(loc, 0, type); + { + e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type)); + e->type = type; + e = e->optimize(result); + } else { e2 = e2->optimize(WANTflags); @@ -355,7 +360,11 @@ e1 = e1->optimize(WANTflags); e = this; if (e1->isBool(TRUE)) - e = new IntegerExp(loc, 1, type); + { // Replace with (e1, 1) + e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type)); + e->type = type; + e = e->optimize(result); + } else { e2 = e2->optimize(WANTflags); diff -uNr dmd-0.152/dmd/src/dmd/root.h dmd-0.153/dmd/src/dmd/root.h --- dmd-0.152/dmd/src/dmd/root.h 2005-12-02 00:51:42.000000000 +0100 +++ dmd-0.153/dmd/src/dmd/root.h 2006-04-05 09:36:48.000000000 +0200 @@ -225,10 +225,10 @@ // Return <0 this < f // =0 this == f // >0 this > f - int File::compareTime(File *f); + int compareTime(File *f); // Read system file statistics - void File::stat(); + void stat(); /* Set buffer */ @@ -284,7 +284,7 @@ void printf(const unsigned short *format, ...); #endif void bracket(char left, char right); - unsigned OutBuffer::bracket(unsigned i, char *left, unsigned j, char *right); + unsigned bracket(unsigned i, char *left, unsigned j, char *right); void spread(unsigned offset, unsigned nbytes); unsigned insert(unsigned offset, const void *data, unsigned nbytes); void remove(unsigned offset, unsigned nbytes); diff -uNr dmd-0.152/dmd/src/dmd/statement.c dmd-0.153/dmd/src/dmd/statement.c --- dmd-0.152/dmd/src/dmd/statement.c 2006-03-30 19:05:14.000000000 +0200 +++ dmd-0.153/dmd/src/dmd/statement.c 2006-04-06 01:53:20.000000000 +0200 @@ -196,6 +196,7 @@ { exp = exp->semantic(sc); exp = resolveProperties(sc, exp); exp->checkSideEffect(0); + exp = exp->optimize(WANTvalue); } return this; } @@ -2046,7 +2047,6 @@ if (tbret->ty != Tvoid) exp = exp->implicitCastTo(tret); } - exp = exp->optimize(WANTvalue); //exp->dump(0); //exp->print(); exp->checkEscape(); diff -uNr dmd-0.152/dmd/src/dmd/staticassert.c dmd-0.153/dmd/src/dmd/staticassert.c --- dmd-0.152/dmd/src/dmd/staticassert.c 2006-02-27 23:32:16.000000000 +0100 +++ dmd-0.153/dmd/src/dmd/staticassert.c 2006-04-09 15:27:56.000000000 +0200 @@ -51,7 +51,10 @@ if (e->isBool(FALSE)) error("(%s) is false", exp->toChars()); else if (!e->isBool(TRUE)) + { error("(%s) is not evaluatable at compile time", exp->toChars()); +printf("%s\n", e->toChars()); + } } int StaticAssert::oneMember(Dsymbol **ps) diff -uNr dmd-0.152/dmd/src/phobos/internal/aaA.d dmd-0.153/dmd/src/phobos/internal/aaA.d --- dmd-0.152/dmd/src/phobos/internal/aaA.d 2006-04-03 01:19:10.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/internal/aaA.d 2006-04-10 13:42:48.000000000 +0200 @@ -678,13 +678,16 @@ return result; } - foreach (e; aa.a.b) + if (aa.a) { - if (e) + foreach (e; aa.a.b) { - result = treewalker(e); - if (result) - break; + if (e) + { + result = treewalker(e); + if (result) + break; + } } } return result; @@ -728,13 +731,16 @@ return result; } - foreach (e; aa.a.b) + if (aa.a) { - if (e) + foreach (e; aa.a.b) { - result = treewalker(e); - if (result) - break; + if (e) + { + result = treewalker(e); + if (result) + break; + } } } return result; diff -uNr dmd-0.152/dmd/src/phobos/internal/arraycat.d dmd-0.153/dmd/src/phobos/internal/arraycat.d --- dmd-0.152/dmd/src/phobos/internal/arraycat.d 2006-04-03 01:19:10.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/internal/arraycat.d 2006-04-10 13:42:48.000000000 +0200 @@ -98,7 +98,9 @@ if (to.length != from.length) { - throw new Error(std.string.format("lengths don't match for array copy, %s = %s", to.length, from.length)); + //throw new Error(std.string.format("lengths don't match for array copy, %s = %s", to.length, from.length)); + throw new Error("lengths don't match for array copy," ~ + toString(to.length) ~ " = " ~ toString(from.length)); } else if (cast(byte *)to + to.length * size <= cast(byte *)from || cast(byte *)from + from.length * size <= cast(byte *)to) diff -uNr dmd-0.152/dmd/src/phobos/internal/object.d dmd-0.153/dmd/src/phobos/internal/object.d --- dmd-0.152/dmd/src/phobos/internal/object.d 2006-04-03 01:19:10.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/internal/object.d 2006-04-10 13:42:48.000000000 +0200 @@ -9,7 +9,7 @@ */ /* - * Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com + * Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com * Written by Walter Bright * * This software is provided 'as-is', without any express or implied @@ -62,6 +62,7 @@ * analogous to C's ptrdiff_t. */ alias long ptrdiff_t; + alias ulong hash_t; } else @@ -563,7 +564,7 @@ char[] name; size_t xsize; - uint function(void*) xtoHash; + hash_t function(void*) xtoHash; int function(void*,void*) xopEquals; int function(void*,void*) xopCmp; } diff -uNr dmd-0.152/dmd/src/phobos/object.d dmd-0.153/dmd/src/phobos/object.d --- dmd-0.152/dmd/src/phobos/object.d 2006-04-03 01:19:08.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/object.d 2006-04-10 13:42:46.000000000 +0200 @@ -8,7 +8,7 @@ alias typeof(int.sizeof) size_t; alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t; -alias uint hash_t; +alias size_t hash_t; extern (C) { int printf(char *, ...); diff -uNr dmd-0.152/dmd/src/phobos/std/conv.d dmd-0.153/dmd/src/phobos/std/conv.d --- dmd-0.152/dmd/src/phobos/std/conv.d 2006-04-03 01:19:08.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/conv.d 2006-04-10 13:42:46.000000000 +0200 @@ -1,12 +1,51 @@ -// Written by Walter Bright -// Copyright (c) 2002-2006 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. +/* + * Copyright (C) 2002-2006 by Digital Mars, www.digitalmars.com + * Written by Walter Bright + * Some parts contributed by David L. Davis + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * o The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * o Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * o This notice may not be removed or altered from any source + * distribution. + */ + +/*********** + * Conversion building blocks. These differ from the C equivalents + * atoi() and atol() by + * checking for overflow and not allowing whitespace. + * + * For conversion to signed types, the grammar recognized is: + *
+$(I Integer): + $(I Sign UnsignedInteger) + $(I UnsignedInteger) + +$(I Sign): + $(B +) + $(B -) + *+ * For conversion to signed types, the grammar recognized is: + *
+$(I UnsignedInteger): + $(I DecimalDigit) + $(I DecimalDigit) $(I UnsignedInteger) + *+ * Macros: + * WIKI=Phobos/StdConv + */ module std.conv; @@ -18,8 +57,11 @@ //debug=conv; // uncomment to turn on debugging printf's -/************** Exceptions ****************/ +/* ************* Exceptions *************** */ +/** + * Thrown on conversion errors, which happens on deviation from the grammar. + */ class ConvError : Error { this(char[] s) @@ -33,6 +75,9 @@ throw new ConvError(s); } +/** + * Thrown on conversion overflow errors. + */ class ConvOverflowError : Error { this(char[] s) @@ -47,9 +92,7 @@ } /*************************************************************** - * Convert character string to int. - * Grammar: - * ['+'|'-'] digit {digit} + * Convert character string to the return type. */ int toInt(char[] s) @@ -173,9 +216,7 @@ /******************************************************* - * Convert character string to uint. - * Grammar: - * digit {digit} + * ditto */ uint toUint(char[] s) @@ -269,10 +310,8 @@ } } -/*************************************************************** - * Convert character string to long. - * Grammar: - * ['+'|'-'] digit {digit} +/******************************************************* + * ditto */ long toLong(char[] s) @@ -402,9 +441,7 @@ /******************************************************* - * Convert character string to ulong. - * Grammar: - * digit {digit} + * ditto */ ulong toUlong(char[] s) @@ -506,10 +543,8 @@ } -/*************************************************************** - * Convert character string to short. - * Grammar: - * ['+'|'-'] digit {digit} +/******************************************************* + * ditto */ short toShort(char[] s) @@ -592,9 +627,7 @@ /******************************************************* - * Convert character string to ushort. - * Grammar: - * digit {digit} + * ditto */ ushort toUshort(char[] s) @@ -671,10 +704,8 @@ } -/*************************************************************** - * Convert character string to byte. - * Grammar: - * ['+'|'-'] digit {digit} +/******************************************************* + * ditto */ byte toByte(char[] s) @@ -757,9 +788,7 @@ /******************************************************* - * Convert character string to ubyte. - * Grammar: - * digit {digit} + * ditto */ ubyte toUbyte(char[] s) @@ -836,8 +865,8 @@ } -/*************************************************************** - * Convert character string to float. +/******************************************************* + * ditto */ float toFloat(in char[] s) @@ -899,8 +928,8 @@ assert(toString(f) == toString(float.nan)); } -/*************************************************************** - * Convert character string to double. +/******************************************************* + * ditto */ double toDouble(in char[] s) @@ -965,10 +994,8 @@ //assert(cast(real)d == cast(real)double.nan); } -/*************************************************************** - * Convert character string to real. - * Grammar: - * ['+'|'-'] digit {digit} +/******************************************************* + * ditto */ real toReal(in char[] s) { @@ -1045,8 +1072,8 @@ * Should it match what toString(ifloat) does with the 'i' suffix? */ -/*************************************************************** - * Convert character string to ifloat. +/******************************************************* + * ditto */ ifloat toIfloat(in char[] s) @@ -1083,8 +1110,8 @@ assert(feq(cast(ireal)ift, cast(ireal)ifloat.nan)); } -/*************************************************************** - * Convert character string to idouble. +/******************************************************* + * ditto */ idouble toIdouble(in char[] s) @@ -1122,8 +1149,8 @@ assert(toString(id) == toString(idouble.nan)); } -/*************************************************************** - * Convert character string to ireal. +/******************************************************* + * ditto */ ireal toIreal(in char[] s) @@ -1162,10 +1189,9 @@ assert(toString(ir) == toString(ireal.nan)); } -/*************************************************************** - * Convert character string to cfloat. - * Grammar: - * ['+'|'-'] digit {digit} + +/******************************************************* + * ditto */ cfloat toCfloat(in char[] s) { @@ -1243,10 +1269,8 @@ assert(feq(cast(creal)cf, cast(creal)cfloat.nan)); } -/*************************************************************** - * Convert character string to cdouble. - * Grammar: - * ['+'|'-'] digit {digit} +/******************************************************* + * ditto */ cdouble toCdouble(in char[] s) { @@ -1320,10 +1344,8 @@ assert(feq(cast(creal)cd, cast(creal)cdouble.nan)); } -/*************************************************************** - * Convert character string to creal. - * Grammar: - * ['+'|'-'] digit {digit} +/******************************************************* + * ditto */ creal toCreal(in char[] s) { @@ -1414,7 +1436,7 @@ } -/*************************************************************** +/* ************************************************************** * Splits a complex float (cfloat, cdouble, and creal) into two workable strings. * Grammar: * ['+'|'-'] string floating-point digit {digit} @@ -1468,7 +1490,7 @@ // feq() functions now used only in unittesting -/**************************************** +/* *************************************** * Main function to compare reals with given precision */ private bool feq(in real rx, in real ry, in real precision) @@ -1485,7 +1507,7 @@ return cast(bool)(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. @@ -1507,7 +1529,7 @@ return cast(bool)(feq(r1, r2, 0.000001L)); } -/**************************************** +/* *************************************** * compare ireals with given precision */ private bool feq(in ireal r1, in ireal r2) @@ -1527,7 +1549,7 @@ return feq(rx, ry, 0.000001L); } -/**************************************** +/* *************************************** * compare creals with given precision */ private bool feq(in creal r1, in creal r2) diff -uNr dmd-0.152/dmd/src/phobos/std/cstream.d dmd-0.153/dmd/src/phobos/std/cstream.d --- dmd-0.152/dmd/src/phobos/std/cstream.d 2006-04-03 01:19:08.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/cstream.d 2006-04-10 13:42:46.000000000 +0200 @@ -1,6 +1,10 @@ /** + * The std.cstream module bridges std.c.stdio (or std.stdio) and std.stream. + * Both std.c.stdio and std.stream are publicly imported by std.cstream. * Authors: Ben Hinkle - * License: public domain + * License: Public Domain + * Macros: + * WIKI=Phobos/StdCstream */ module std.cstream; @@ -8,11 +12,19 @@ import std.stream; import std.c.stdio; -// wraps a FILE* in a stream class +/** + * A Stream wrapper for a C file of type FILE*. + */ class CFile : Stream { FILE* cfile; - // Construct a CFile from the given FILE* with mode and optional seekable state + /** + * Create the stream wrapper for the given C file. + * Params: + * mode = a bitwise combination of $(B FileMode.In) for a readable file + * and $(B FileMode.Out) for a writeable file. + * seekable = indicates if the stream should be _seekable. + */ this(FILE* cfile, FileMode mode, bool seekable = false) { super(); this.file = cfile; @@ -21,51 +33,103 @@ this.seekable = seekable; } + /** + * Closes the stream. + */ ~this() { close(); } + /** + * Property to get or set the underlying file for this stream. + * Setting the file marks the stream as open. + */ FILE* file() { return cfile; } + + /** + * Ditto + */ void file(FILE* cfile) { this.cfile = cfile; isopen = true; } + /** + * Overrides of the $(B Stream) methods to call the underlying $(B FILE*) + * C functions. + */ override void flush() { fflush(cfile); } + + /** + * Ditto + */ override void close() { if (isopen) fclose(cfile); isopen = readable = writeable = seekable = false; } + + /** + * Ditto + */ override bool eof() { return cast(bool)(readEOF || feof(cfile)); } + + /** + * Ditto + */ override char getc() { return cast(char)fgetc(cfile); } + + /** + * Ditto + */ override char ungetc(char c) { return cast(char)std.c.stdio.ungetc(c,cfile); } + + /** + * Ditto + */ override size_t readBlock(void* buffer, size_t size) { size_t n = fread(buffer,1,size,cfile); readEOF = cast(bool)(n == 0); return n; } + + /** + * Ditto + */ override size_t writeBlock(void* buffer, size_t size) { return fwrite(buffer,1,size,cfile); } + + /** + * Ditto + */ 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); } + + /** + * Ditto + */ override void writeLine(char[] s) { writeString(s); writeString("\n"); } + + /** + * Ditto + */ override void writeLineW(wchar[] s) { writeStringW(s); writeStringW("\n"); } + // run a few tests unittest { FILE* f = fopen("stream.txt","w"); @@ -140,8 +204,20 @@ } } -// standard IO devices -CFile din, dout, derr; +/** + * CFile wrapper of std.c.stdio.stdin (not seekable). + */ +CFile din; + +/** + * CFile wrapper of std.c.stdio.stdout (not seekable). + */ +CFile dout; + +/** + * CFile wrapper of std.c.stdio.stderr (not seekable). + */ +CFile derr; static this() { // open standard I/O devices diff -uNr dmd-0.152/dmd/src/phobos/std/ctype.d dmd-0.153/dmd/src/phobos/std/ctype.d --- dmd-0.152/dmd/src/phobos/std/ctype.d 2006-04-03 01:19:08.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/ctype.d 2006-04-10 13:42:46.000000000 +0200 @@ -1,44 +1,87 @@ - /* - * Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com - * Written by Walter Bright - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, in both source and binary form, subject to the following - * restrictions: - * - * o The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * o Altered source versions must be plainly marked as such, and must not - * be misrepresented as being the original software. - * o This notice may not be removed or altered from any source - * distribution. + * Placed into the Public Domain. + * Digital Mars, www.digitalmars.com + * Written by Walter Bright */ -// Simple ASCII char classification functions +/** + * Simple ASCII character classification functions. + * For Unicode classification, see $(LINK2 std_uni.html, std.uni). + * References: + * $(LINK2 http://www.digitalmars.com/d/ascii-table.html, ASCII Table), + * $(LINK2 http://en.wikipedia.org/wiki/Ascii, Wikipedia) + * Macros: + * WIKI=Phobos/StdCtype + */ module std.ctype; +/** + * Returns !=0 if c is a letter in the range (0..9, a..z, A..Z). + */ int isalnum(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG) : 0; } + +/** + * Returns !=0 if c is an ascii upper or lower case letter. + */ int isalpha(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP) : 0; } + +/** + * Returns !=0 if c is a control character. + */ int iscntrl(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_CTL) : 0; } + +/** + * Returns !=0 if c is a digit. + */ int isdigit(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_DIG) : 0; } + +/** + * Returns !=0 if c is lower case ascii letter. + */ int islower(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_LC) : 0; } + +/** + * Returns !=0 if c is a punctuation character. + */ int ispunct(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_PNC) : 0; } + +/** + * Returns !=0 if c is a space, tab, vertical tab, form feed, + * carriage return, or linefeed. + */ int isspace(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_SPC) : 0; } + +/** + * Returns !=0 if c is an upper case ascii character. + */ int isupper(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_UC) : 0; } + +/** + * Returns !=0 if c is a hex digit (0..9, a..f, A..F). + */ int isxdigit(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_HEX) : 0; } + +/** + * Returns !=0 if c is a printing character except for the space character. + */ int isgraph(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG|_PNC) : 0; } + +/** + * Returns !=0 if c is a printing character except for the space character. + */ int isprint(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG|_PNC|_BLK) : 0; } + +/** + * Returns !=0 if c is in the ascii character set, i.e. in the range 0..0x7F. + */ int isascii(dchar c) { return c <= 0x7F; } + +/** + * If c is an upper case ascii character, + * return the lower case equivalent, otherwise return c. + */ dchar tolower(dchar c) out (result) { @@ -49,6 +92,11 @@ return isupper(c) ? c + (cast(dchar)'a' - 'A') : c; } + +/** + * If c is a lower case ascii character, + * return the upper case equivalent, otherwise return c. + */ dchar toupper(dchar c) out (result) { diff -uNr dmd-0.152/dmd/src/phobos/std/date.d dmd-0.153/dmd/src/phobos/std/date.d --- dmd-0.152/dmd/src/phobos/std/date.d 2006-04-03 01:19:08.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/date.d 2006-04-10 13:42:46.000000000 +0200 @@ -34,19 +34,23 @@ */ const d_time d_time_nan = long.min; +/** + * Time broken down into its components. + */ struct Date { - int year = int.min; // our "nan" Date value - int month; // 1..12 - int day; // 1..31 - int hour; // 0..23 - int minute; // 0..59 - int second; // 0..59 - int ms; // 0..999 - int weekday; // 0: not specified - // 1..7: Sunday..Saturday - int tzcorrection = int.min; // -1200..1200 correction in hours + int year = int.min; /// use int.min as "nan" year value + int month; /// 1..12 + int day; /// 1..31 + int hour; /// 0..23 + int minute; /// 0..59 + int second; /// 0..59 + int ms; /// 0..999 + int weekday; /// 0: not specified + /// 1..7: Sunday..Saturday + int tzcorrection = int.min; /// -1200..1200 correction in hours + /// Parse date out of string s[] and store it in this Date instance. void parse(char[] s) { DateParse dp; @@ -220,7 +224,9 @@ { int y; // Hazard a guess - y = 1970 + cast(int) (t / (365.2425 * msPerDay)); + //y = 1970 + cast(int) (t / (365.2425 * msPerDay)); + // Use integer only math + y = 1970 + cast(int) (t / (3652425 * (msPerDay / 10000))); if (TimeFromYear(y) <= t) { @@ -360,7 +366,8 @@ return t - LocalTZA - DaylightSavingTA(t - LocalTZA); } -d_time MakeTime(int hour, int min, int sec, int ms) + +d_time MakeTime(d_time hour, d_time min, d_time sec, d_time ms) { return hour * TicksPerHour + min * TicksPerMinute + @@ -369,7 +376,7 @@ } -d_time MakeDay(int year, int month, int date) +d_time MakeDay(d_time year, d_time month, d_time date) { d_time t; int y; int m; diff -uNr dmd-0.152/dmd/src/phobos/std/format.d dmd-0.153/dmd/src/phobos/std/format.d --- dmd-0.152/dmd/src/phobos/std/format.d 2006-04-03 01:19:08.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/format.d 2006-04-10 13:42:46.000000000 +0200 @@ -50,8 +50,11 @@ version (DigitalMarsC) { // This is DMC's internal floating point formatting function - extern (C) char* function(int c, int flags, int precision, real* pdval, - char* buf, int* psl, int width) __pfloatfmt; + extern (C) + { + extern char* function(int c, int flags, int precision, real* pdval, + char* buf, int* psl, int width) __pfloatfmt; + } } else { @@ -126,6 +129,7 @@ private TypeInfo primitiveTypeInfo(Mangle m) { TypeInfo ti; + switch (m) { case Mangle.Tvoid: @@ -835,6 +839,27 @@ goto Lerror; } + if (!signed) + { + switch (m) + { + case Mangle.Tbyte: + vnumber &= 0xFF; + break; + + case Mangle.Tshort: + vnumber &= 0xFFFF; + break; + + case Mangle.Tint: + vnumber &= 0xFFFFFFFF; + break; + + default: + break; + } + } + if (flags & FLprecision && fc != 'p') flags &= ~FL0pad; @@ -1294,5 +1319,29 @@ dchar dc = 'a'; r = std.string.format("%d", dc); assert(r == "97"); + + byte b = byte.max; + r = std.string.format("%x", b); + assert(r == "7f"); + r = std.string.format("%x", ++b); + assert(r == "80"); + r = std.string.format("%x", ++b); + assert(r == "81"); + + short sh = short.max; + r = std.string.format("%x", sh); + assert(r == "7fff"); + r = std.string.format("%x", ++sh); + assert(r == "8000"); + r = std.string.format("%x", ++sh); + assert(r == "8001"); + + i = int.max; + r = std.string.format("%x", i); + assert(r == "7fffffff"); + r = std.string.format("%x", ++i); + assert(r == "80000000"); + r = std.string.format("%x", ++i); + assert(r == "80000001"); } diff -uNr dmd-0.152/dmd/src/phobos/std/gc.d dmd-0.153/dmd/src/phobos/std/gc.d --- dmd-0.152/dmd/src/phobos/std/gc.d 2006-04-03 01:19:08.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/gc.d 2006-04-10 13:42:46.000000000 +0200 @@ -1,21 +1,75 @@ -// Copyright (c) 1999-2003 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com +/* + * Copyright (C) 1999-2006 by Digital Mars, www.digitalmars.com + * Written by Walter Bright + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * o The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * o Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * o This notice may not be removed or altered from any source + * distribution. + */ + + +/** + * The garbage collector normally works behind the scenes without needing any + * specific interaction. These functions are for advanced applications that + * benefit from tuning the operation of the collector. + * Macros: + * WIKI=Phobos/StdGc + */ module std.gc; import gcstats; +/** + * Add p to list of roots. Roots are references to memory allocated by the + collector that are maintained in memory outside the collector pool. The garbage + collector will by default look for roots in the stacks of each thread, the + registers, and the default static data segment. If roots are held elsewhere, + use addRoot() or addRange() to tell the collector not to free the memory it + points to. + */ void addRoot(void *p); // add p to list of roots + +/** + * Remove p from list of roots. + */ void removeRoot(void *p); // remove p from list of roots +/** + * Add range to scan for roots. + */ void addRange(void *pbot, void *ptop); // add range to scan for roots + +/** + * Remove range. + */ void removeRange(void *pbot); // remove range /*********************************** * Run a full garbage collection cycle. + * + * The collector normally runs synchronously with a storage allocation request + (i.e. it never happens when in code that does not allocate memory). In some + circumstances, for example when a particular task is finished, it is convenient + to explicitly run the collector and free up all memory used by that task. It + can also be helpful to run a collection before starting a new task that would + be annoying if it ran a collection in the middle of that task. Explicitly + running a collection can also be done in a separate very low priority thread, + so that if the program is idly waiting for input, memory can be cleaned up. */ void fullCollect(); @@ -27,17 +81,31 @@ */ void genCollect(); + void genCollectNoStack(); -void minimize(); // minimize physical memory usage +/** + * Minimizes physical memory usage + */ +void minimize(); /*************************************** - * Disable and enable collections. They must be - * a matched pair, and can nest. + * disable() temporarilly disables garbage collection cycle, enable() + * then reenables them. + * + * This is used for brief time + critical sections of code, so the amount of time it will take is predictable. + If the collector runs out of memory while it is disabled, it will throw an + OutOfMemory exception. The disable() function calls can be nested, but must be + matched with corresponding enable() calls. * By default collections are enabled. */ void disable(); + +/** + * ditto + */ void enable(); void getStats(out GCStats stats); diff -uNr dmd-0.152/dmd/src/phobos/std/intrinsic.d dmd-0.153/dmd/src/phobos/std/intrinsic.d --- dmd-0.152/dmd/src/phobos/std/intrinsic.d 2006-04-03 01:19:08.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/intrinsic.d 2006-04-10 13:42:46.000000000 +0200 @@ -5,25 +5,170 @@ // Placed into the public domain /** These functions are built-in intrinsics to the compiler. + * + Intrinsic functions are functions built in to the compiler, + usually to take advantage of specific CPU features that + are inefficient to handle via external functions. + The compiler's optimizer and code generator are fully + integrated in with intrinsic functions, bringing to bear + their full power on them. + This can result in some surprising speedups. + * Macros: + * WIKI=Phobos/StdIntrinsic */ module std.intrinsic; +/** + * Scans the bits in v starting with bit 0, looking + * for the first set bit. + * Returns: + * The bit number of the first bit set. + * The return value is undefined if v is zero. + */ int bsf(uint v); + +/** + * Scans the bits in v from the most significant bit + * to the least significant bit, looking + * for the first set bit. + * Returns: + * The bit number of the first bit set. + * The return value is undefined if v is zero. + * Example: + * --- + * import std.intrinsic; + * + * int main() + * { + * uint v; + * int x; + * + * v = 0x21; + * x = bsf(v); + * printf("bsf(x%x) = %d\n", v, x); + * x = bsr(v); + * printf("bsr(x%x) = %d\n", v, x); + * return 0; + * } + * --- + * Output: + * bsf(x21) = 0
+btc(array, 35) = 0 +array = [0]:x2, [1]:x108 +btc(array, 35) = -1 +array = [0]:x2, [1]:x100 +bts(array, 35) = 0 +array = [0]:x2, [1]:x108 +btr(array, 35) = -1 +array = [0]:x2, [1]:x100 +bt(array, 1) = -1 +array = [0]:x2, [1]:x100 ++ */ int bts(uint *p, uint bitnum); + +/** + * Swaps bytes in a 4 byte uint end-to-end, i.e. byte 0 becomes + byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3 + becomes byte 0. + */ uint bswap(uint v); -ubyte inp(uint); -ushort inpw(uint); -uint inpl(uint); - -ubyte outp(uint, ubyte); -ushort outpw(uint, ushort); -uint outpl(uint, uint); + +/** + * Reads I/O port at port_address. + */ +ubyte inp(uint port_address); + +/** + * ditto + */ +ushort inpw(uint port_address); + +/** + * ditto + */ +uint inpl(uint port_address); + + +/** + * Writes and returns value to I/O port at port_address. + */ +ubyte outp(uint port_address, ubyte value); + +/** + * ditto + */ +ushort outpw(uint port_address, ushort value); + +/** + * ditto + */ +uint outpl(uint port_address, uint value); diff -uNr dmd-0.152/dmd/src/phobos/std/regexp.d dmd-0.153/dmd/src/phobos/std/regexp.d --- dmd-0.152/dmd/src/phobos/std/regexp.d 2006-04-03 01:19:08.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/regexp.d 2006-04-10 13:42:46.000000000 +0200 @@ -2480,11 +2480,10 @@ void optimize() { ubyte[] prog; - int i; debug(regexp) printf("RegExp.optimize()\n"); prog = buf.toBytes(); - for (i = 0; 1;) + for (size_t i = 0; 1;) { //printf("\tprog[%d] = %d, %d\n", i, prog[i], REstring); switch (prog[i]) @@ -2564,10 +2563,9 @@ uint n; uint m; ubyte* pop; - int i; //printf("RegExp.starrchars(prog = %p, progend = %p)\n", prog, progend); - for (i = 0; i < prog.length;) + for (size_t i = 0; i < prog.length;) { switch (prog[i]) { @@ -2774,31 +2772,28 @@ private static rchar[] replace3(rchar[] format, rchar[] input, regmatch_t[] pmatch) { - OutBuffer buf; rchar[] result; - rchar c; uint c2; int rm_so; int rm_eo; int i; - int f; // printf("replace3(format = '%.*s', input = '%.*s')\n", format, input); - buf = new OutBuffer(); - buf.reserve(format.length * rchar.sizeof); - for (f = 0; f < format.length; f++) + result.length = format.length; + result.length = 0; + for (size_t f = 0; f < format.length; f++) { - c = format[f]; + auto c = format[f]; L1: if (c != '$') { - buf.write(c); + result ~= c; continue; } ++f; if (f == format.length) { - buf.write(cast(rchar)'$'); + result ~= '$'; break; } c = format[f]; @@ -2826,8 +2821,8 @@ { if (i == 0) { - buf.write(cast(rchar)'$'); - buf.write(c); + result ~= '$'; + result ~= c; continue; } } @@ -2840,8 +2835,8 @@ } if (i == 0) { - buf.write(cast(rchar)'$'); - buf.write(c); + result ~= '$'; + result ~= c; c = c2; goto L1; } @@ -2856,16 +2851,15 @@ Lstring: if (rm_so != rm_eo) - buf.write(input[rm_so .. rm_eo]); + result ~= input[rm_so .. rm_eo]; break; default: - buf.write(cast(rchar)'$'); - buf.write(c); + result ~= '$'; + result ~= c; break; } } - result = cast(rchar[])buf.toBytes(); return result; } @@ -2891,22 +2885,20 @@ public rchar[] replaceOld(rchar[] format) { - OutBuffer buf; rchar[] result; - rchar c; //printf("replace: this = %p so = %d, eo = %d\n", this, pmatch[0].rm_so, pmatch[0].rm_eo); //printf("3input = '%.*s'\n", input); - buf = new OutBuffer(); - buf.reserve(format.length * rchar.sizeof); - for (uint i; i < format.length; i++) + result.length = format.length; + result.length = 0; + for (size_t i; i < format.length; i++) { - c = format[i]; + auto c = format[i]; switch (c) { case '&': //printf("match = '%.*s'\n", input[pmatch[0].rm_so .. pmatch[0].rm_eo]); - buf.write(input[pmatch[0].rm_so .. pmatch[0].rm_eo]); + result ~= input[pmatch[0].rm_so .. pmatch[0].rm_eo]; break; case '\\': @@ -2918,19 +2910,18 @@ i = c - '0'; if (i <= re_nsub && pmatch[i].rm_so != pmatch[i].rm_eo) - buf.write(input[pmatch[i].rm_so .. pmatch[i].rm_eo]); + result ~= input[pmatch[i].rm_so .. pmatch[i].rm_eo]; break; } } - buf.write(c); + result ~= c; break; default: - buf.write(c); + result ~= c; break; } } - result = cast(rchar[])buf.toBytes(); return result; } diff -uNr dmd-0.152/dmd/src/phobos/std/socket.d dmd-0.153/dmd/src/phobos/std/socket.d --- dmd-0.152/dmd/src/phobos/std/socket.d 2006-04-03 01:19:08.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/socket.d 2006-04-10 13:42:46.000000000 +0200 @@ -24,6 +24,14 @@ Thanks to Benjamin Herr for his assistance. */ +/** + * Notes: For Win32 systems, link with ws2_32.lib. + * Example: See /dmd/samples/d/listener.d. + * Authors: Christopher E. Miller + * Macros: + * WIKI=Phobos/StdSocket + */ + module std.socket; private import std.string, std.stdint, std.c.string, std.c.stdlib; @@ -71,9 +79,10 @@ } +/// Base exception thrown from a Socket. class SocketException: Exception { - int errorCode; // Platform-specific error code. + int errorCode; /// Platform-specific error code. this(char[] msg, int err = 0) @@ -127,47 +136,58 @@ } } - +/** + * The communication domain used to resolve an address. + */ enum AddressFamily: int { - UNSPEC = AF_UNSPEC, - UNIX = AF_UNIX, - INET = AF_INET, - IPX = AF_IPX, - APPLETALK = AF_APPLETALK, - INET6 = AF_INET6, + UNSPEC = AF_UNSPEC, /// + UNIX = AF_UNIX, /// local communication + INET = AF_INET, /// internet protocol version 4 + IPX = AF_IPX, /// novell IPX + APPLETALK = AF_APPLETALK, /// appletalk + INET6 = AF_INET6, // internet protocol version 6 } +/** + * Communication semantics + */ enum SocketType: int { - STREAM = SOCK_STREAM, - DGRAM = SOCK_DGRAM, - RAW = SOCK_RAW, - RDM = SOCK_RDM, - SEQPACKET = SOCK_SEQPACKET, + STREAM = SOCK_STREAM, /// sequenced, reliable, two-way communication-based byte streams + DGRAM = SOCK_DGRAM, /// connectionless, unreliable datagrams with a fixed maximum length; data may be lost or arrive out of order + RAW = SOCK_RAW, /// raw protocol access + RDM = SOCK_RDM, /// reliably-delivered message datagrams + SEQPACKET = SOCK_SEQPACKET, /// sequenced, reliable, two-way connection-based datagrams with a fixed maximum length } +/** + * Protocol + */ enum ProtocolType: int { - IP = IPPROTO_IP, - ICMP = IPPROTO_ICMP, - IGMP = IPPROTO_IGMP, - GGP = IPPROTO_GGP, - TCP = IPPROTO_TCP, - PUP = IPPROTO_PUP, - UDP = IPPROTO_UDP, - IDP = IPPROTO_IDP, - IPV6 = IPPROTO_IPV6, + IP = IPPROTO_IP, /// internet protocol version 4 + ICMP = IPPROTO_ICMP, /// internet control message protocol + IGMP = IPPROTO_IGMP, /// internet group management protocol + GGP = IPPROTO_GGP, /// gateway to gateway protocol + TCP = IPPROTO_TCP, /// transmission control protocol + PUP = IPPROTO_PUP, /// PARC universal packet protocol + UDP = IPPROTO_UDP, /// user datagram protocol + IDP = IPPROTO_IDP, /// Xerox NS protocol + IPV6 = IPPROTO_IPV6, /// internet protocol version 6 } +/** + * Protocol is a class for retrieving protocol information. + */ class Protocol { - ProtocolType type; - char[] name; - char[][] aliases; + ProtocolType type; /// These members are populated when one of the following functions are called without failure: + char[] name; /// ditto + char[][] aliases; /// ditto void populate(protoent* proto) @@ -196,7 +216,7 @@ } } - + /** Returns false on failure */ bool getProtocolByName(char[] name) { protoent* proto; @@ -208,6 +228,7 @@ } + /** Returns false on failure */ // Same as getprotobynumber(). bool getProtocolByType(ProtocolType type) { @@ -233,12 +254,16 @@ } +/** + * Service is a class for retrieving service information. + */ class Service { + /** These members are populated when one of the following functions are called without failure: */ char[] name; - char[][] aliases; - ushort port; - char[] protocolName; + char[][] aliases; /// ditto + ushort port; /// ditto + char[] protocolName; /// ditto void populate(servent* serv) @@ -268,7 +293,10 @@ } } - + /** + * If a protocol name is omitted, any protocol will be matched. + * Returns: false on failure. + */ bool getServiceByName(char[] name, char[] protocolName) { servent* serv; @@ -281,6 +309,7 @@ // Any protocol name will be matched. + /// ditto bool getServiceByName(char[] name) { servent* serv; @@ -292,6 +321,7 @@ } + /// ditto bool getServiceByPort(ushort port, char[] protocolName) { servent* serv; @@ -304,6 +334,7 @@ // Any protocol name will be matched. + /// ditto bool getServiceByPort(ushort port) { servent* serv; @@ -335,9 +366,12 @@ } +/** + * Base exception thrown from an InternetHost. + */ class HostException: Exception { - int errorCode; + int errorCode; /// Platform-specific error code. this(char[] msg, int err = 0) @@ -347,12 +381,15 @@ } } - +/** + * InternetHost is a class for resolving IPv4 addresses. + */ class InternetHost { + /** These members are populated when one of the following functions are called without failure: */ char[] name; - char[][] aliases; - uint32_t[] addrList; + char[][] aliases; /// ditto + uint32_t[] addrList; /// ditto void validHostent(hostent* he) @@ -410,7 +447,9 @@ } } - + /** + * Resolve host name. Returns false if unable to resolve. + */ bool getHostByName(char[] name) { hostent* he = gethostbyname(toStringz(name)); @@ -422,6 +461,9 @@ } + /** + * Resolve IPv4 address number. Returns false if unable to resolve. + */ bool getHostByAddr(uint addr) { uint x = htonl(addr); @@ -434,7 +476,11 @@ } - //shortcut + /** + * Same as previous, but addr is an IPv4 address string in the + * dotted-decimal form $(I a.b.c.d). + * Returns false if unable to resolve. + */ bool getHostByAddr(char[] addr) { uint x = inet_addr(std.string.toStringz(addr)); @@ -472,6 +518,9 @@ } +/** + * Base exception thrown from an Address. + */ class AddressException: Exception { this(char[] msg) @@ -481,15 +530,20 @@ } +/** + * Address is an abstract class for representing a network addresses. + */ abstract class Address { protected sockaddr* name(); protected int nameLen(); - AddressFamily addressFamily(); - char[] toString(); + AddressFamily addressFamily(); /// Family of this address. + char[] toString(); /// Human readable string representing this address. } - +/** + * + */ class UnknownAddress: Address { protected: @@ -522,6 +576,10 @@ } +/** + * InternetAddress is a class that represents an IPv4 (internet protocol version + * 4) address and port. + */ class InternetAddress: Address { protected: @@ -546,31 +604,35 @@ public: - const uint ADDR_ANY = INADDR_ANY; - const uint ADDR_NONE = INADDR_NONE; - const ushort PORT_ANY = 0; - + const uint ADDR_ANY = INADDR_ANY; /// Any IPv4 address number. + const uint ADDR_NONE = INADDR_NONE; /// An invalid IPv4 address number. + const ushort PORT_ANY = 0; /// Any IPv4 port number. + /// Overridden to return AddressFamily.INET. AddressFamily addressFamily() { return cast(AddressFamily)AddressFamily.INET; } - + /// Returns the IPv4 port number. ushort port() { return ntohs(sin.sin_port); } - + /// Returns the IPv4 address number. uint addr() { return ntohl(sin.sin_addr.s_addr); } - - //-port- can be PORT_ANY - //-addr- is an IP address or host name + /** + * Params: + * addr = an IPv4 address string in the dotted-decimal form a.b.c.d, + * or a host name that will be resolved using an InternetHost + * object. + * port = may be PORT_ANY as stated below. + */ this(char[] addr, ushort port) { uint uiaddr = parse(addr); @@ -586,41 +648,48 @@ sin.sin_port = htons(port); } - + /** + * Construct a new Address. addr may be ADDR_ANY (default) and port may + * be PORT_ANY, and the actual numbers may not be known until a connection + * is made. + */ this(uint addr, ushort port) { sin.sin_addr.s_addr = htonl(addr); sin.sin_port = htons(port); } - + /// ditto this(ushort port) { sin.sin_addr.s_addr = 0; //any, "0.0.0.0" sin.sin_port = htons(port); } - + /// Human readable string representing the IPv4 address in dotted-decimal form. char[] toAddrString() { return std.string.toString(inet_ntoa(sin.sin_addr)).dup; } - + /// Human readable string representing the IPv4 port. char[] toPortString() { return std.string.toString(port()); } - + /// Human readable string representing the IPv4 address and port in the form $(I a.b.c.d:e). char[] toString() { return toAddrString() ~ ":" ~ toPortString(); } - - //-addr- is an IP address in the format "a.b.c.d" - //returns ADDR_NONE on failure + /** + * Parse an IPv4 address string in the dotted-decimal form $(I a.b.c.d) + * and return the number. + * If the string is not a legitimate IPv4 address, + * ADDR_NONE is returned. + */ static uint parse(char[] addr) { return ntohl(inet_addr(std.string.toStringz(addr))); @@ -635,6 +704,7 @@ } +/** */ class SocketAcceptException: SocketException { this(char[] msg, int err = 0) @@ -643,30 +713,32 @@ } } - +/// How a socket is shutdown: enum SocketShutdown: int { - RECEIVE = SD_RECEIVE, - SEND = SD_SEND, - BOTH = SD_RECEIVE, + RECEIVE = SD_RECEIVE, /// socket receives are disallowed + SEND = SD_SEND, /// socket sends are disallowed + BOTH = SD_RECEIVE, /// both RECEIVE and SEND } +/// Flags may be OR'ed together: enum SocketFlags: int { - NONE = 0, + NONE = 0, /// no flags specified - OOB = MSG_OOB, //out of band - PEEK = MSG_PEEK, //only for receiving - DONTROUTE = MSG_DONTROUTE, //only for sending + OOB = MSG_OOB, /// out-of-band stream data + PEEK = MSG_PEEK, /// peek at incoming data without removing it from the queue, only for receiving + DONTROUTE = MSG_DONTROUTE, /// data should not be subject to routing; this flag may be ignored. Only for sending } +/// Duration timeout value. extern(C) struct timeval { // D interface - int seconds; - int microseconds; + int seconds; /// Number of seconds. + int microseconds; /// Number of additional microseconds. // C interface deprecated @@ -677,7 +749,7 @@ } -//a set of sockets for Socket.select() +/// A collection of sockets for use with Socket.select. class SocketSet { private: @@ -723,6 +795,8 @@ public: + + /// Set the maximum amount of sockets that may be added. this(uint max) { version(Win32) @@ -740,13 +814,13 @@ } } - + /// Uses the default maximum for the system. this() { this(FD_SETSIZE); } - + /// Reset the SocketSet so that there are 0 Sockets in the collection. void reset() { version(Win32) @@ -785,38 +859,38 @@ } } - + /// Add a Socket to the collection. Adding more than the maximum has dangerous side affects. void add(Socket s) { add(s.sock); } - void remove(socket_t s) { FD_CLR(s, _fd_set); } + /// Remove this Socket from the collection. void remove(Socket s) { remove(s.sock); } - int isSet(socket_t s) { return FD_ISSET(s, _fd_set); } + /// Returns nonzero if this Socket is in the collection. int isSet(Socket s) { return isSet(s.sock); } - - // Max sockets that can be added, like FD_SETSIZE. + + // Return maximum amount of sockets that can be added, like FD_SETSIZE. uint max() { version(Win32) @@ -854,28 +928,29 @@ } +/// The level at which a socket option is defined: enum SocketOptionLevel: int { - SOCKET = SOL_SOCKET, - IP = ProtocolType.IP, - ICMP = ProtocolType.ICMP, - IGMP = ProtocolType.IGMP, - GGP = ProtocolType.GGP, - TCP = ProtocolType.TCP, - PUP = ProtocolType.PUP, - UDP = ProtocolType.UDP, - IDP = ProtocolType.IDP, - IPV6 = ProtocolType.IPV6, + SOCKET = SOL_SOCKET, /// socket level + IP = ProtocolType.IP, /// internet protocol version 4 level + ICMP = ProtocolType.ICMP, /// + IGMP = ProtocolType.IGMP, /// + GGP = ProtocolType.GGP, /// + TCP = ProtocolType.TCP, /// transmission control protocol level + PUP = ProtocolType.PUP, /// + UDP = ProtocolType.UDP, /// user datagram protocol level + IDP = ProtocolType.IDP, /// + IPV6 = ProtocolType.IPV6, /// internet protocol version 6 level } - +/// Linger information for use with SocketOption.LINGER. extern(C) struct linger { // D interface version(Win32) { - uint16_t on; - uint16_t time; + uint16_t on; /// Nonzero for on. + uint16_t time; /// Linger time. } else version(BsdSockets) { @@ -892,29 +967,34 @@ } +/// Specifies a socket option: enum SocketOption: int { - DEBUG = SO_DEBUG, - BROADCAST = SO_BROADCAST, - REUSEADDR = SO_REUSEADDR, - LINGER = SO_LINGER, - OOBINLINE = SO_OOBINLINE, - SNDBUF = SO_SNDBUF, - RCVBUF = SO_RCVBUF, - DONTROUTE = SO_DONTROUTE, + DEBUG = SO_DEBUG, /// record debugging information + BROADCAST = SO_BROADCAST, /// allow transmission of broadcast messages + REUSEADDR = SO_REUSEADDR, /// allow local reuse of address + LINGER = SO_LINGER, /// linger on close if unsent data is present + OOBINLINE = SO_OOBINLINE, /// receive out-of-band data in band + SNDBUF = SO_SNDBUF, /// send buffer size + RCVBUF = SO_RCVBUF, /// receive buffer size + DONTROUTE = SO_DONTROUTE, /// do not route // SocketOptionLevel.TCP: - TCP_NODELAY = .TCP_NODELAY, + TCP_NODELAY = .TCP_NODELAY, /// disable the Nagle algorithm for send coalescing // SocketOptionLevel.IPV6: - IPV6_UNICAST_HOPS = .IPV6_UNICAST_HOPS, - IPV6_MULTICAST_IF = .IPV6_MULTICAST_IF, - IPV6_MULTICAST_LOOP = .IPV6_MULTICAST_LOOP, - IPV6_JOIN_GROUP = .IPV6_JOIN_GROUP, - IPV6_LEAVE_GROUP = .IPV6_LEAVE_GROUP, + IPV6_UNICAST_HOPS = .IPV6_UNICAST_HOPS, /// + IPV6_MULTICAST_IF = .IPV6_MULTICAST_IF, /// + IPV6_MULTICAST_LOOP = .IPV6_MULTICAST_LOOP, /// + IPV6_JOIN_GROUP = .IPV6_JOIN_GROUP, /// + IPV6_LEAVE_GROUP = .IPV6_LEAVE_GROUP, /// } +/** + * Socket is a class that creates a network communication endpoint using the + * Berkeley sockets interface. + */ class Socket { private: @@ -922,7 +1002,7 @@ AddressFamily _family; version(Win32) - bool _blocking = false; + bool _blocking = false; /// Property to get or set whether the socket is blocking or nonblocking. // For use with accepting(). @@ -932,6 +1012,12 @@ public: + + /** + * Create a blocking socket. If a single protocol type exists to support + * this socket type within the address family, the ProtocolType may be + * omitted. + */ this(AddressFamily af, SocketType type, ProtocolType protocol) { sock = cast(socket_t)socket(af, type, protocol); @@ -943,12 +1029,14 @@ // A single protocol exists to support this socket type within the // protocol family, so the ProtocolType is assumed. + /// ditto this(AddressFamily af, SocketType type) { this(af, type, cast(ProtocolType)0); // Pseudo protocol number. } + /// ditto this(AddressFamily af, SocketType type, char[] protocolName) { protoent* proto; @@ -1012,27 +1100,32 @@ throw new SocketException("Unable to set socket blocking", _lasterr()); } - + + /// Get the socket's address family. AddressFamily addressFamily() // getter { return _family; } - + /// Property that indicates if this is a valid, alive socket. bool isAlive() // getter { int type, typesize = type.sizeof; return !getsockopt(sock, SOL_SOCKET, SO_TYPE, cast(char*)&type, &typesize); } - + /// Associate a local address with this socket. void bind(Address addr) { if(_SOCKET_ERROR == .bind(sock, addr.name(), addr.nameLen())) throw new SocketException("Unable to bind socket", _lasterr()); } - + /** + * Establish a connection. If the socket is blocking, connect waits for + * the connection to be made. If the socket is nonblocking, connect + * returns immediately and the connection attempt is still in progress. + */ void connect(Address to) { if(_SOCKET_ERROR == .connect(sock, to.name(), to.nameLen())) @@ -1061,15 +1154,23 @@ } } - - //need to bind() first + /** + * Listen for an incoming connection. bind must be called before you can + * listen. The backlog is a request of how many pending incoming + * connections are queued until accept'ed. + */ void listen(int backlog) { if(_SOCKET_ERROR == .listen(sock, backlog)) throw new SocketException("Unable to listen on socket", _lasterr()); } - + /** + * Called by accept when a new Socket must be created for a new + * connection. To use a derived class, override this method and return an + * instance of your class. The returned Socket's handle must not be set; + * Socket has a protected constructor this() to use in this situation. + */ // Override to use a derived class. // The returned socket's handle must not be set. protected Socket accepting() @@ -1077,7 +1178,11 @@ return new Socket; } - + /** + * Accept an incoming connection. If the socket is blocking, accept + * waits for a connection request. Throws SocketAcceptException if unable + * to accept. See accepting for use with derived classes. + */ Socket accept() { socket_t newsock; @@ -1107,7 +1212,7 @@ return newSocket; } - + /// Disables sends and/or receives. void shutdown(SocketShutdown how) { .shutdown(sock, cast(int)how); @@ -1126,7 +1231,12 @@ } } - + + /** + * Immediately drop any connections and release socket resources. + * Calling shutdown before close is recommended for connection-oriented + * sockets. The Socket object is no longer usable after close. + */ //calling shutdown() before this is recommended //for connection-oriented sockets void close() @@ -1152,7 +1262,7 @@ } - // Returns the local machine's host name. Idea from mango. + /// Returns the local machine's host name. Idea from mango. static char[] hostName() // getter { char[256] result; // Host names are limited to 255 chars. @@ -1161,7 +1271,7 @@ return std.string.toString(cast(char*)result).dup; } - + /// Remote endpoint Address. Address remoteAddress() { Address addr = newFamilyObject(); @@ -1172,7 +1282,7 @@ return addr; } - + /// Local endpoint Address. Address localAddress() { Address addr = newFamilyObject(); @@ -1183,10 +1293,14 @@ return addr; } - + /// Send or receive error code. const int ERROR = _SOCKET_ERROR; - + /** + * Send data on the connection. Returns the number of bytes actually + * sent, or ERROR on failure. If the socket is blocking and there is no + * buffer space left, send waits. + */ //returns number of bytes actually sent, or -1 on error int send(void[] buf, SocketFlags flags) { @@ -1194,20 +1308,22 @@ return sent; } - + /// ditto int send(void[] buf) { return send(buf, SocketFlags.NONE); } - + /** + * Send data to a specific destination Address. If the destination address is not specified, a connection must have been made and that address is used. If the socket is blocking and there is no buffer space left, sendTo waits. + */ int sendTo(void[] buf, SocketFlags flags, Address to) { int sent = .sendto(sock, buf, buf.length, cast(int)flags, to.name(), to.nameLen()); return sent; } - + /// ditto int sendTo(void[] buf, Address to) { return sendTo(buf, SocketFlags.NONE, to); @@ -1215,6 +1331,7 @@ //assumes you connect()ed + /// ditto int sendTo(void[] buf, SocketFlags flags) { int sent = .sendto(sock, buf, buf.length, cast(int)flags, null, 0); @@ -1223,12 +1340,19 @@ //assumes you connect()ed + /// ditto int sendTo(void[] buf) { return sendTo(buf, SocketFlags.NONE); } - + + /** + * Receive data on the connection. Returns the number of bytes actually + * received, 0 if the remote side has closed the connection, or ERROR on + * failure. If the socket is blocking, receive waits until there is data + * to be received. + */ //returns number of bytes actually received, 0 on connection closure, or -1 on error int receive(void[] buf, SocketFlags flags) { @@ -1239,13 +1363,15 @@ return read; } - + /// ditto int receive(void[] buf) { return receive(buf, SocketFlags.NONE); } - + /** + * Receive data and get the remote endpoint Address. Returns the number of bytes actually received, 0 if the remote side has closed the connection, or ERROR on failure. If the socket is blocking, receiveFrom waits until there is data to be received. + */ int receiveFrom(void[] buf, SocketFlags flags, out Address from) { if(!buf.length) //return 0 and don't think the connection closed @@ -1259,6 +1385,7 @@ } + /// ditto int receiveFrom(void[] buf, out Address from) { return receiveFrom(buf, SocketFlags.NONE, from); @@ -1266,6 +1393,7 @@ //assumes you connect()ed + /// ditto int receiveFrom(void[] buf, SocketFlags flags) { if(!buf.length) //return 0 and don't think the connection closed @@ -1277,12 +1405,14 @@ //assumes you connect()ed + /// ditto int receiveFrom(void[] buf) { return receiveFrom(buf, SocketFlags.NONE); } - + + /// Get a socket option. Returns the number of bytes written to result. //returns the length, in bytes, of the actual result - very different from getsockopt() int getOption(SocketOptionLevel level, SocketOption option, void[] result) { @@ -1292,21 +1422,22 @@ return len; } - - // Common case for integer and boolean options. + + /// Common case of getting integer and boolean options. int getOption(SocketOptionLevel level, SocketOption option, out int32_t result) { return getOption(level, option, (&result)[0 .. 1]); } - - + + + /// Get the linger option. int getOption(SocketOptionLevel level, SocketOption option, out linger result) { //return getOption(cast(SocketOptionLevel)SocketOptionLevel.SOCKET, SocketOption.LINGER, (&result)[0 .. 1]); return getOption(level, option, (&result)[0 .. 1]); } - + // Set a socket option. void setOption(SocketOptionLevel level, SocketOption option, void[] value) { if(_SOCKET_ERROR == .setsockopt(sock, cast(int)level, cast(int)option, value, value.length)) @@ -1314,20 +1445,24 @@ } - // Common case for integer and boolean options. + /// Common case for setting integer and boolean options. void setOption(SocketOptionLevel level, SocketOption option, int32_t value) { setOption(level, option, (&value)[0 .. 1]); } - - + + + /// Set the linger option. void setOption(SocketOptionLevel level, SocketOption option, linger value) { //setOption(cast(SocketOptionLevel)SocketOptionLevel.SOCKET, SocketOption.LINGER, (&value)[0 .. 1]); setOption(level, option, (&value)[0 .. 1]); } - + + /** + * Wait for a socket to change status. A wait timeout timeval or int microseconds may be specified; if a timeout is not specified or the timeval is null, the maximum timeout is used. The timeval timeout has an unspecified value when select returns. Returns the number of sockets with status changes, 0 on timeout, or -1 on interruption. If the return value is greater than 0, the SocketSets are updated to only contain the sockets having status changes. For a connecting socket, a write status change means the connection is established and it's able to send. For a listening socket, a read status change means there is an incoming connection request and it's able to accept. + */ //SocketSet's updated to include only those sockets which an event occured //returns the number of events, 0 on timeout, or -1 on interruption //for a connect()ing socket, writeability means connected @@ -1420,8 +1555,9 @@ return result; } - - + + + /// ditto static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, int microseconds) { timeval tv; @@ -1431,6 +1567,7 @@ } + /// ditto //maximum timeout static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError) { @@ -1448,14 +1585,16 @@ } +/// TcpSocket is a shortcut class for a TCP Socket. class TcpSocket: Socket { + /// Constructs a blocking TCP Socket. this(AddressFamily family) { super(family, SocketType.STREAM, ProtocolType.TCP); } - + /// Constructs a blocking TCP Socket. this() { this(cast(AddressFamily)AddressFamily.INET); @@ -1463,6 +1602,7 @@ //shortcut + /// Constructs a blocking TCP Socket and connects to an InternetAddress. this(Address connectTo) { this(connectTo.addressFamily()); @@ -1471,14 +1611,17 @@ } +/// UdpSocket is a shortcut class for a UDP Socket. class UdpSocket: Socket { + /// Constructs a blocking UDP Socket. this(AddressFamily family) { super(family, SocketType.DGRAM, ProtocolType.UDP); } + /// Constructs a blocking UDP Socket. this() { this(cast(AddressFamily)AddressFamily.INET); diff -uNr dmd-0.152/dmd/src/phobos/std/string.d dmd-0.153/dmd/src/phobos/std/string.d --- dmd-0.152/dmd/src/phobos/std/string.d 2006-04-03 01:19:08.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/string.d 2006-04-10 13:42:46.000000000 +0200 @@ -102,9 +102,8 @@ real atof(char[] s) { char* endptr; - real result; - result = strtold(toStringz(s), &endptr); + auto result = strtold(toStringz(s), &endptr); return result; } @@ -120,7 +119,7 @@ int cmp(char[] s1, char[] s2) { - size_t len = s1.length; + auto len = s1.length; int result; //printf("cmp('%.*s', '%.*s')\n", s1, s2); @@ -138,7 +137,7 @@ int icmp(char[] s1, char[] s2) { - size_t len = s1.length; + auto len = s1.length; int result; if (s2.length < len) @@ -272,11 +271,9 @@ int find(char[] s, dchar c) { - char* p; - if (c <= 0x7F) { // Plain old ASCII - p = cast(char*)memchr(s, c, s.length); + auto p = cast(char*)memchr(s, c, s.length); if (p) return p - cast(char *)s; else @@ -502,17 +499,17 @@ } body { - size_t sublength = sub.length; + auto sublength = sub.length; if (sublength == 0) return 0; if (s.length >= sublength) { - char c = sub[0]; + auto c = sub[0]; if (sublength == 1) { - char *p = cast(char*)memchr(s, c, s.length); + auto p = cast(char*)memchr(s, c, s.length); if (p) return p - &s[0]; } @@ -577,7 +574,7 @@ } body { - size_t sublength = sub.length; + auto sublength = sub.length; int i; if (sublength == 0) @@ -586,7 +583,7 @@ if (s.length < sublength) return -1; - char c = sub[0]; + auto c = sub[0]; if (sublength == 1) { i = ifind(s, c); @@ -600,7 +597,7 @@ for (i = 0; i < imax; i++) { - int j = ifind(s[i .. imax], c); + auto j = ifind(s[i .. imax], c); if (j == -1) return -1; i += j; @@ -817,7 +814,7 @@ changed = 0; for (i = 0; i < s.length; i++) { - char c = s[i]; + auto c = s[i]; if ('A' <= c && c <= 'Z') { if (!changed) @@ -872,7 +869,7 @@ changed = 0; for (i = 0; i < s.length; i++) { - char c = s[i]; + auto c = s[i]; if ('a' <= c && c <= 'z') { if (!changed) @@ -989,12 +986,10 @@ char[] capwords(char[] s) { char[] r; - int inword; - int i; - int istart; + bool inword = false; + size_t istart = 0; + size_t i; - istart = 0; - inword = 0; for (i = 0; i < s.length; i++) { switch (s[i]) @@ -1008,7 +1003,7 @@ if (inword) { r ~= capitalize(s[istart .. i]); - inword = 0; + inword = false; } break; @@ -1018,7 +1013,7 @@ if (r.length) r ~= ' '; istart = i; - inword = 1; + inword = true; } break; } @@ -1058,7 +1053,7 @@ if (s.length == 1) r[] = s[0]; else - { size_t len = s.length; + { auto len = s.length; for (size_t i = 0; i < n * len; i += len) { @@ -1095,23 +1090,22 @@ char[] join(char[][] words, char[] sep) { - size_t len; - uint seplen; - uint i; - uint j; char[] result; if (words.length) { - len = 0; + size_t len = 0; + size_t i; + for (i = 0; i < words.length; i++) len += words[i].length; - seplen = sep.length; + auto seplen = sep.length; len += (words.length - 1) * seplen; result = new char[len]; + size_t j; i = 0; while (true) { @@ -1157,12 +1151,11 @@ char[][] split(char[] s) { - uint i; - uint istart; - int inword; + size_t i; + size_t istart = 0; + bool inword = false; char[][] words; - inword = 0; for (i = 0; i < s.length; i++) { switch (s[i]) @@ -1176,14 +1169,14 @@ if (inword) { words ~= s[istart .. i]; - inword = 0; + inword = false; } break; default: if (!inword) { istart = i; - inword = 1; + inword = true; } break; } @@ -1224,8 +1217,8 @@ } body { - uint i; - uint j; + size_t i; + size_t j; char[][] words; i = 0; @@ -1233,9 +1226,9 @@ { if (delim.length == 1) { char c = delim[0]; - uint nwords = 0; - char *p = &s[0]; - char *pend = p + s.length; + size_t nwords = 0; + char* p = &s[0]; + char* pend = p + s.length; while (true) { @@ -1274,7 +1267,7 @@ assert(wordi + 1 == nwords); } else - { uint nwords = 0; + { size_t nwords = 0; while (true) { @@ -1522,10 +1515,10 @@ char[] chomp(char[] s, char[] delimiter = null) { if (delimiter is null) - { size_t len = s.length; + { auto len = s.length; if (len) - { char c = s[len - 1]; + { auto c = s[len - 1]; if (c == '\r') // if ends in CR len--; @@ -1589,7 +1582,7 @@ */ char[] chop(char[] s) -{ size_t len = s.length; +{ auto len = s.length; if (len) { @@ -1713,7 +1706,7 @@ { char[] p; int i; - int istart; + size_t istart; //printf("replace('%.*s','%.*s','%.*s')\n", s, from, to); if (from.length == 0) @@ -2457,7 +2450,7 @@ char[20] buffer; sprintf(buffer, "%g", d); - return toString(buffer).dup; + return std.string.toString(buffer).dup; } /// ditto @@ -2466,7 +2459,7 @@ char[20] buffer; sprintf(buffer, "%Lg", r); - return toString(buffer).dup; + return std.string.toString(buffer).dup; } /// ditto @@ -2478,7 +2471,7 @@ char[21] buffer; sprintf(buffer, "%gi", d); - return toString(buffer).dup; + return std.string.toString(buffer).dup; } /// ditto @@ -2487,7 +2480,7 @@ char[21] buffer; sprintf(buffer, "%Lgi", r); - return toString(buffer).dup; + return std.string.toString(buffer).dup; } /// ditto @@ -2499,7 +2492,7 @@ char[20 + 1 + 20 + 1] buffer; sprintf(buffer, "%g+%gi", d.re, d.im); - return toString(buffer).dup; + return std.string.toString(buffer).dup; } /// ditto @@ -2508,9 +2501,10 @@ char[20 + 1 + 20 + 1] buffer; sprintf(buffer, "%Lg+%Lgi", r.re, r.im); - return toString(buffer).dup; + return std.string.toString(buffer).dup; } + /****************************************** * Convert value to string in _radix radix. * @@ -2903,13 +2897,13 @@ dchar lastc; size_t lasti; int run; - int changed; + bool changed; foreach (size_t i, dchar c; s) { if (run && lastc == c) { - changed = 1; + changed = true; } else if (pattern is null || inPattern(c, pattern)) { @@ -3770,9 +3764,9 @@ * leftmost column, which is numbered starting from 0. */ -int column(char[] string, int tabsize = 8) +size_t column(char[] string, int tabsize = 8) { - int column; + size_t column; foreach (dchar c; string) { diff -uNr dmd-0.152/dmd/src/phobos/std/system.d dmd-0.153/dmd/src/phobos/std/system.d --- dmd-0.152/dmd/src/phobos/std/system.d 2006-04-03 01:19:08.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/system.d 2006-04-10 13:42:46.000000000 +0200 @@ -1,10 +1,12 @@ /** + * Information about the target operating system, environment, and CPU * Authors: Walter Bright, www.digitalmars.com * License: Public Domain + * Macros: + * WIKI = Phobos/StdSystem */ -// Information about the target operating system, environment, and CPU module std.system; @@ -44,12 +46,17 @@ RedHatLinux, } - // Big-endian or Little-endian? + /// Byte order endiannes - enum Endian { BigEndian, LittleEndian } + enum Endian + { + BigEndian, /// big endian byte order + LittleEndian /// little endian byte order + } version(LittleEndian) { + /// Native system endiannes Endian endian = Endian.LittleEndian; } else diff -uNr dmd-0.152/dmd/src/phobos/std/thread.d dmd-0.153/dmd/src/phobos/std/thread.d --- dmd-0.152/dmd/src/phobos/std/thread.d 2006-04-03 01:19:08.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/thread.d 2006-04-10 13:42:46.000000000 +0200 @@ -50,11 +50,17 @@ stdfp start_addr, void* arglist, uint initflag, thread_id* thrdaddr); -// This is equivalent to a HANDLE from windows.d +/** + * The type of the thread handle used by the operating system. + * For Windows, it is equivalent to a HANDLE from windows.d. + */ alias HANDLE thread_hdl; alias uint thread_id; +/** + * Thrown for errors. + */ class ThreadError : Error { this(char[] s) @@ -63,27 +69,48 @@ } } +/** + * One of these is created for each thread. + */ class Thread { + /** + * Constructor used by classes derived from Thread that override main(). + */ this() { } + /** + * Constructor used by classes derived from Thread that override run(). + */ this(int (*fp)(void *), void *arg) { this.fp = fp; this.arg = arg; } + /** + * Constructor used by classes derived from Thread that override run(). + */ this(int delegate() dg) { this.dg = dg; } + /** + * The handle to this thread assigned by the operating system. This is set + * to thread_id.init if the thread hasn't been started yet. + */ thread_hdl hdl; + thread_id id; void* stackBottom; + /** + * Create a new thread and start it running. The new thread initializes + * itself and then calls run(). start() can only be called once. + */ void start() { if (state != TS.INITIAL) @@ -116,6 +143,12 @@ } } + /** + * Entry point for a thread. If not overridden, it calls the function + * pointer fp and argument arg passed in the constructor, or the delegate + * dg. + * Returns: the thread exit code, which is normally 0. + */ int run() { if (fp) @@ -159,26 +192,39 @@ } } + /** + * The state of a thread. + */ enum TS { - INITIAL, - RUNNING, - TERMINATED + INITIAL, /// The thread hasn't been started yet. + RUNNING, /// The thread is running or paused. + TERMINATED /// The thread has ended. } + /** + * Returns the state of a thread. + */ TS getState() { return state; } + /** + * The priority of a thread. + */ enum PRIORITY { - INCREASE, - DECREASE, - IDLE, - CRITICAL + INCREASE, /// Increase thread priority + DECREASE, /// Decrease thread priority + IDLE, /// Assign thread low priority + CRITICAL /// Assign thread high priority } + /** + * Adjust the priority of this thread. + * Throws: ThreadError if cannot set priority + */ void setPriority(PRIORITY p) { int nPriority; @@ -203,6 +249,10 @@ error("set priority"); } + /** + * Returns a reference to the Thread for the thread that called the + * function. + */ static Thread getThis() { thread_id id; @@ -226,23 +276,35 @@ return result; } + /** + * Returns an array of all the threads currently running. + */ static Thread[] getAll() { return allThreads[0 .. allThreadsDim]; } + /** + * Suspend execution of this thread. + */ void pause() { if (state != TS.RUNNING || SuspendThread(hdl) == 0xFFFFFFFF) error("cannot pause"); } + /** + * Resume execution of this thread. + */ void resume() { if (state != TS.RUNNING || ResumeThread(hdl) == 0xFFFFFFFF) error("cannot resume"); } + /** + * Suspend execution of all threads but this thread. + */ static void pauseAll() { if (nthreads > 1) @@ -259,6 +321,9 @@ } } + /** + * Resume execution of all paused threads. + */ static void resumeAll() { if (nthreads > 1) @@ -275,11 +340,17 @@ } } + /** + * Give up the remainder of this thread's time slice. + */ static void yield() { Sleep(0); } + /** + * + */ static uint nthreads = 1; private: @@ -302,7 +373,7 @@ } - /************************************************ + /* *********************************************** * This is just a wrapper to interface between C rtl and Thread.run(). */ diff -uNr dmd-0.152/dmd/src/phobos/std/typeinfo/ti_AC.d dmd-0.153/dmd/src/phobos/std/typeinfo/ti_AC.d --- dmd-0.152/dmd/src/phobos/std/typeinfo/ti_AC.d 2006-04-03 01:19:10.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/typeinfo/ti_AC.d 2006-04-10 13:42:46.000000000 +0200 @@ -1,7 +1,5 @@ module std.typeinfo.ti_AC; -private import std.string; - // Object[] class TypeInfo_AC : TypeInfo diff -uNr dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Acdouble.d dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Acdouble.d --- dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Acdouble.d 2006-04-03 01:19:10.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Acdouble.d 2006-04-10 13:42:46.000000000 +0200 @@ -23,7 +23,6 @@ module std.typeinfo.ti_Acdouble; -private import std.string; private import std.typeinfo.ti_cdouble; // cdouble[] diff -uNr dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Acfloat.d dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Acfloat.d --- dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Acfloat.d 2006-04-03 01:19:10.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Acfloat.d 2006-04-10 13:42:46.000000000 +0200 @@ -23,7 +23,6 @@ module std.typeinfo.ti_Acfloat; -private import std.string; private import std.typeinfo.ti_cfloat; // cfloat[] diff -uNr dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Acreal.d dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Acreal.d --- dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Acreal.d 2006-04-03 01:19:10.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Acreal.d 2006-04-10 13:42:48.000000000 +0200 @@ -23,7 +23,6 @@ module std.typeinfo.ti_Acreal; -private import std.string; private import std.typeinfo.ti_creal; // creal[] diff -uNr dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Adouble.d dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Adouble.d --- dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Adouble.d 2006-04-03 01:19:10.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Adouble.d 2006-04-10 13:42:46.000000000 +0200 @@ -23,7 +23,6 @@ module std.typeinfo.ti_Adouble; -private import std.string; private import std.typeinfo.ti_double; // double[] diff -uNr dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Afloat.d dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Afloat.d --- dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Afloat.d 2006-04-03 01:19:10.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Afloat.d 2006-04-10 13:42:46.000000000 +0200 @@ -23,7 +23,6 @@ module std.typeinfo.ti_Afloat; -private import std.string; private import std.typeinfo.ti_float; // float[] diff -uNr dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Ag.d dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Ag.d --- dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Ag.d 2006-04-03 01:19:10.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Ag.d 2006-04-10 13:42:46.000000000 +0200 @@ -1,7 +1,6 @@ module std.typeinfo.ti_Ag; -private import std.string; private import std.c.string; // byte[] diff -uNr dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Areal.d dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Areal.d --- dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Areal.d 2006-04-03 01:19:10.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Areal.d 2006-04-10 13:42:46.000000000 +0200 @@ -23,7 +23,6 @@ module std.typeinfo.ti_Areal; -private import std.string; private import std.typeinfo.ti_real; // real[] diff -uNr dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Ashort.d dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Ashort.d --- dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Ashort.d 2006-04-03 01:19:10.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Ashort.d 2006-04-10 13:42:46.000000000 +0200 @@ -1,7 +1,6 @@ module std.typeinfo.ti_Ashort; -private import std.string; private import std.c.string; // short[] diff -uNr dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Aubyte.d dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Aubyte.d --- dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Aubyte.d 2006-04-03 01:19:10.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Aubyte.d 2006-04-10 13:42:46.000000000 +0200 @@ -1,8 +1,8 @@ module std.typeinfo.ti_Aubyte; -private import std.c.string; private import std.string; +private import std.c.string; // ubyte[] diff -uNr dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Aushort.d dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Aushort.d --- dmd-0.152/dmd/src/phobos/std/typeinfo/ti_Aushort.d 2006-04-03 01:19:10.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/typeinfo/ti_Aushort.d 2006-04-10 13:42:46.000000000 +0200 @@ -2,7 +2,6 @@ module std.typeinfo.ti_Aushort; private import std.c.string; -private import std.string; // ushort[] diff -uNr dmd-0.152/dmd/src/phobos/std/typeinfo/ti_C.d dmd-0.153/dmd/src/phobos/std/typeinfo/ti_C.d --- dmd-0.152/dmd/src/phobos/std/typeinfo/ti_C.d 2006-04-03 01:19:10.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/typeinfo/ti_C.d 2006-04-10 13:42:46.000000000 +0200 @@ -23,8 +23,6 @@ module std.typeinfo.ti_C; -private import std.string; - // Object class TypeInfo_C : TypeInfo diff -uNr dmd-0.152/dmd/src/phobos/std/uni.d dmd-0.153/dmd/src/phobos/std/uni.d --- dmd-0.152/dmd/src/phobos/std/uni.d 2006-04-03 01:19:08.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std/uni.d 2006-04-10 13:42:46.000000000 +0200 @@ -1,6 +1,26 @@ +/* + * Placed into the Public Domain. + * Digital Mars, www.digitalmars.com + * Written by Walter Bright + */ + +/** + * Simple Unicode character classification functions. + * For ASCII classification, see $(LINK2 std_ctype.html, std.ctype). + * Macros: + * WIKI=Phobos/StdUni + * References: + * $(LINK2 http://www.digitalmars.com/d/ascii-table.html, ASCII Table), + * $(LINK2 http://en.wikipedia.org/wiki/Unicode, Wikipedia), + * $(LINK2 http://www.unicode.org, The Unicode Consortium) + */ + module std.uni; +/** + * Returns !=0 if c is a Unicode lower case character. + */ int isUniLower(dchar c) { if (c <= 0x7F) @@ -9,6 +29,9 @@ return isUniAlpha(c) && c == toUniLower(c); } +/** + * Returns !=0 if c is a Unicode upper case character. + */ int isUniUpper(dchar c) { if (c <= 0x7F) @@ -17,6 +40,10 @@ return isUniAlpha(c) && c == toUniUpper(c); } +/** + * If c is a Unicode upper case character, return the lower case + * equivalent, otherwise return c. + */ dchar toUniLower(dchar c) { if (c >= 'A' && c <= 'Z') @@ -79,6 +106,10 @@ return c; } +/** + * If c is a Unicode lower case character, return the upper case + * equivalent, otherwise return c. + */ dchar toUniUpper(dchar c) { if (c >= 'a' && c <= 'z') @@ -143,7 +174,7 @@ /******************************* - * Return !=0 if unicode alpha. + * Return !=0 if u is a Unicode alpha character. */ int isUniAlpha(dchar u) diff -uNr dmd-0.152/dmd/src/phobos/std.ddoc dmd-0.153/dmd/src/phobos/std.ddoc --- dmd-0.152/dmd/src/phobos/std.ddoc 2006-04-03 01:19:08.000000000 +0200 +++ dmd-0.153/dmd/src/phobos/std.ddoc 2006-04-10 13:42:46.000000000 +0200 @@ -79,6 +79,7 @@ std.string