diff -uNr dmd-0.134/dmd/src/dmd/cond.c dmd-0.135/dmd/src/dmd/cond.c --- dmd-0.134/dmd/src/dmd/cond.c 2005-09-19 14:39:42.000000000 +0200 +++ dmd-0.135/dmd/src/dmd/cond.c 2005-10-03 02:30:44.000000000 +0200 @@ -277,7 +277,6 @@ { if (!sc) { -*(char*)0=0; error(loc, "iftype conditional cannot be at global scope"); inc = 2; return 0; diff -uNr dmd-0.134/dmd/src/dmd/cond.h dmd-0.135/dmd/src/dmd/cond.h --- dmd-0.134/dmd/src/dmd/cond.h 2005-06-16 13:00:46.000000000 +0200 +++ dmd-0.135/dmd/src/dmd/cond.h 2005-10-03 02:30:42.000000000 +0200 @@ -84,7 +84,6 @@ { /* iftype (targ id tok tspec) */ - Loc loc; Type *targ; Identifier *id; // can be NULL enum TOK tok; // ':' or '==' diff -uNr dmd-0.134/dmd/src/dmd/doc.c dmd-0.135/dmd/src/dmd/doc.c --- dmd-0.134/dmd/src/dmd/doc.c 2005-09-28 16:38:04.000000000 +0200 +++ dmd-0.135/dmd/src/dmd/doc.c 2005-10-02 21:20:18.000000000 +0200 @@ -26,6 +26,7 @@ #include "dsymbol.h" #include "macro.h" #include "template.h" +#include "lexer.h" #include "doc.h" struct Section @@ -57,6 +58,7 @@ Section *summary; Section *copyright; + Section *macros; Macro **pmacrotable; DocComment(); @@ -77,25 +79,9 @@ unsigned skippastident(OutBuffer *buf, unsigned i); void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset); void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset); +void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset); Argument *isFunctionParameter(Dsymbol *s, unsigned char *p, unsigned len); -static unsigned char default_boilerplate[] = "\ -\n\ -\n\ -\n\ -$(TITLE)\n\ -\n\ -\n\ -

$(TITLE)

\n\ -
\n\ -$(BODY)\n\ -
\n\ -
\n\ -Last modified: $(DATETIME)
\n\ -$(COPYRIGHT)
\n\ -\n\ -"; - static unsigned char ddoc_default[] = "\ DDOC = \n\ \n\ @@ -134,6 +120,11 @@ WHITE = $0\n\ \n\ D_CODE =
$0
\n\ +D_COMMENT = $(GREEN $0)\n\ +D_STRING = $(RED $0)\n\ +D_KEYWORD = $(BLUE $0)\n\ +D_PSYMBOL = $(U $0)\n\ +D_PARAM = $(I $0)\n\ \n\ DDOC_DECL = $(DT $(BIG $0))\n\ DDOC_DECL_DD = $(DD $0)\n\ @@ -153,13 +144,14 @@ DDOC_STANDARDS = $(B Standards:)$(BR)\n$0$(BR)$(BR)\n\ DDOC_THROWS = $(B Throws:)$(BR)\n$0$(BR)$(BR)\n\ DDOC_VERSION = $(B Version:)$(BR)\n$0$(BR)$(BR)\n\ -DDOC_SECTION_H = $(B $0)$(BR)$(BR)\n\ +DDOC_SECTION_H = $(B $0)$(BR)\n\ DDOC_SECTION = $0$(BR)$(BR)\n\ DDOC_MEMBERS = $(DL $0)\n\ -DDOC_PARAMS = $(TABLE $0)$(BR)$(BR)\n\ +DDOC_PARAMS = $(B Params:)$(BR)\n$(TABLE $0)$(BR)\n\ DDOC_PARAM_ROW = $(TR $0)\n\ DDOC_PARAM_ID = $(TD $0)\n\ -DDOC_PARAM_DESC = $(TD $0)\n\ +DDOC_PARAM_DESC = $(TD $0)\n\ +DDOC_BLANKLINE = $(BR)$(BR)\n\ \n\ DDOC_PSYMBOL = $(U $0)\n\ DDOC_KEYWORD = $(B $0)\n\ @@ -239,8 +231,23 @@ buf.printf("\n", srcfile->toChars()); - dc->writeSections(sc, this, sc->docbuf); - emitMemberComments(sc); + if (isDocFile) + { + size_t commentlen = strlen((char *)comment); + if (dc->macros) + { + commentlen = dc->macros->name - comment; + dc->macros->write(dc, sc, this, sc->docbuf); + } + sc->docbuf->write(comment, commentlen); + highlightText(NULL, this, sc->docbuf, 0); + } + else + { + + dc->writeSections(sc, this, sc->docbuf); + emitMemberComments(sc); + } Macro::define(¯otable, (unsigned char *)"BODY", 4, buf.data, buf.offset); @@ -332,15 +339,18 @@ void ScopeDsymbol::emitMemberComments(Scope *sc) { + //printf("ScopeDsymbol::emitMemberComments()\n"); OutBuffer *buf = sc->docbuf; if (members) { + // BUG: if no members are actually printed, we should not emit DDOC_MEMBERS buf->writestring("$(DDOC_MEMBERS \n"); sc = sc->push(this); for (int i = 0; i < members->dim; i++) { Dsymbol *s = (Dsymbol *)members->data[i]; + //printf("\ts = '%s'\n", s->toChars()); s->emitComment(sc); } sc->pop(); @@ -477,7 +487,16 @@ if (prot() == PROTprivate) return; if (!comment) + { if (isAnonymous() && members) + { + for (int i = 0; i < members->dim; i++) + { + Dsymbol *s = (Dsymbol *)members->data[i]; + s->emitComment(sc); + } + } return; + } OutBuffer *buf = sc->docbuf; DocComment *dc = DocComment::parse(sc, this, comment); @@ -707,6 +726,10 @@ { dc->copyright = s; } + if (icmp("macros", s->name, s->namelen) == 0) + { + dc->macros = s; + } } sc->lastdc = dc; @@ -1122,6 +1145,10 @@ p++; textlen = p - textstart; + // Remove trailing \r if there is one + if (p > m && p[-1] == '\r') + textlen--; + p++; //printf("p = %p, pend = %p\n", p, pend); @@ -1307,15 +1334,11 @@ break; case '\n': - if (i == iLineStart) // if "\n\n" + if (sc && !inCode && i == iLineStart && i + 1 < buf->offset) // if "\n\n" { -#if 1 - buf->insert(i, "$(BR)$(BR)\n", 11); - i += 11; // point at last '>' -#else - buf->insert(i, ")\n$(P ", 6); - i += 6; // point at last '>' -#endif + static char blankline[] = "$(DDOC_BLANKLINE)\n"; + + i = buf->insert(i, blankline, sizeof(blankline) - 1); } leadingBlank = 1; iLineStart = i + 1; @@ -1377,8 +1400,8 @@ if (inCode) break; buf->remove(i, 1); - buf->insert(i, ">", 4); - i += 3; // point to ';' + i = buf->insert(i, ">", 4); + i--; // point to ';' break; case '&': @@ -1389,8 +1412,8 @@ if (p[1] == '#' || isalpha(p[1])) break; // already a character entity buf->remove(i, 1); - buf->insert(i, "&", 5); - i += 4; // point to ';' + i = buf->insert(i, "&", 5); + i--; // point to ';' break; case '-': @@ -1399,6 +1422,7 @@ */ if (leadingBlank) { int istart = i; + int eollen = 0; leadingBlank = 0; while (1) @@ -1408,7 +1432,20 @@ break; c = buf->data[i]; if (c == '\n') + { eollen = 1; break; + } + if (c == '\r') + { + eollen = 1; + if (i + 1 >= buf->offset) + break; + if (buf->data[i + 1] == '\n') + { eollen = 2; + break; + } + } + // BUG: handle UTF PS and LS too if (c != '-') goto Lcont; } @@ -1418,7 +1455,7 @@ // We have the start/end of a code section // Remove the entire --- line, including blanks and \n - buf->remove(iLineStart, i - iLineStart + (c == '\n')); + buf->remove(iLineStart, i - iLineStart + eollen); i = iLineStart; if (inCode) @@ -1428,27 +1465,27 @@ OutBuffer codebuf; codebuf.write(buf->data + iCodeStart, i - iCodeStart); - highlightCode(sc, s, &codebuf, 0); + codebuf.writeByte(0); + highlightCode2(sc, s, &codebuf, 0); buf->remove(iCodeStart, i - iCodeStart); - buf->insert(iCodeStart, codebuf.data, codebuf.offset); - i = iCodeStart + codebuf.offset; - buf->insert(i, ")\n", 2); - i += 5; // place i on > + i = buf->insert(iCodeStart, codebuf.data, codebuf.offset); + i = buf->insert(i, ")\n", 2); + i--; } else { static char pre[] = "$(D_CODE \n"; inCode = 1; - buf->insert(i, pre, sizeof(pre) - 1); - i += sizeof(pre) - 2; // place i on > - iCodeStart = i + 2; + i = buf->insert(i, pre, sizeof(pre) - 1); + iCodeStart = i; + i--; // place i on > } } break; default: leadingBlank = 0; - if (!inCode && (isalpha(c) || c == '_')) + if (sc && !inCode && (isalpha(c) || c == '_')) { unsigned j; j = skippastident(buf, i); @@ -1492,7 +1529,7 @@ } /************************************************** - * Highlight code. + * Highlight code for DDOC section. */ void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset) @@ -1507,20 +1544,20 @@ { case '<': // replace '<' with '<' buf->remove(i, 1); - buf->insert(i, "<", 4); - i += 3; // point to ';' + i = buf->insert(i, "<", 4); + i--; // point to ';' break; case '>': buf->remove(i, 1); - buf->insert(i, ">", 4); - i += 3; // point to ';' + i = buf->insert(i, ">", 4); + i--; // point to ';' break; case '&': buf->remove(i, 1); - buf->insert(i, "&", 5); - i += 4; // point to ';' + i = buf->insert(i, "&", 5); + i--; // point to ';' break; default: @@ -1552,3 +1589,98 @@ } } +/**************************************** + */ + +void highlightCode3(OutBuffer *buf, unsigned char *p, unsigned char *pend) +{ + for (; p < pend; p++) + { + switch (*p) + { + case '<': + buf->writestring("<"); + break; + case '>': + buf->writestring(">"); + break; + case '&': + buf->writestring("&"); + break; + default: + buf->writeByte(*p); + break; + } + } +} + +/************************************************** + * Highlight code for CODE section. + */ + + +void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset) +{ + char *sid = s->ident->toChars(); + FuncDeclaration *f = s->isFuncDeclaration(); + unsigned errorsave = global.errors; + Lexer lex(NULL, buf->data, 0, buf->offset - 1, 0, 1); + Token tok; + OutBuffer res; + unsigned char *lastp = buf->data; + char *highlight; + + //printf("highlightCode2('%.*s')\n", buf->offset - 1, buf->data); + res.reserve(buf->offset); + while (1) + { + lex.scan(&tok); + highlightCode3(&res, lastp, tok.ptr); + highlight = NULL; + switch (tok.value) + { + case TOKidentifier: + if (!sc) + break; + if (cmp(sid, tok.ptr, lex.p - tok.ptr) == 0) + { + highlight = "$(D_PSYMBOL "; + break; + } + else if (f) + { + if (isFunctionParameter(f, tok.ptr, lex.p - tok.ptr)) + { + //printf("highlighting arg '%s', i = %d, j = %d\n", arg->ident->toChars(), i, j); + highlight = "$(D_PARAM "; + break; + } + } + break; + + case TOKcomment: + highlight = "$(D_COMMENT "; + break; + + case TOKstring: + highlight = "$(D_STRING "; + break; + + default: + if (tok.isKeyword()) + highlight = "$(D_KEYWORD "; + break; + } + if (highlight) + res.writestring(highlight); + highlightCode3(&res, tok.ptr, lex.p); + if (highlight) + res.writeByte(')'); + if (tok.value == TOKeof) + break; + lastp = lex.p; + } + buf->setsize(offset); + buf->write(&res); + global.errors = errorsave; +} diff -uNr dmd-0.134/dmd/src/dmd/lexer.c dmd-0.135/dmd/src/dmd/lexer.c --- dmd-0.134/dmd/src/dmd/lexer.c 2005-09-22 19:08:32.000000000 +0200 +++ dmd-0.135/dmd/src/dmd/lexer.c 2005-09-29 20:26:38.000000000 +0200 @@ -193,18 +193,21 @@ StringTable Lexer::stringtable; OutBuffer Lexer::stringbuffer; -Lexer::Lexer(Module *mod, unsigned char *base, unsigned length, int doDocComment) +Lexer::Lexer(Module *mod, + unsigned char *base, unsigned begoffset, unsigned endoffset, + int doDocComment, int commentToken) : loc(mod, 1) { //printf("Lexer::Lexer(%p,%d)\n",base,length); //printf("lexer.mod = %p, %p\n", mod, this->loc.mod); memset(&token,0,sizeof(token)); this->base = base; - this->end = base + length; - p = base; + this->end = base + endoffset; + p = base + begoffset; this->mod = mod; this->doDocComment = doDocComment; this->anyToken = 0; + this->commentToken = commentToken; //initKeywords(); } @@ -226,7 +229,7 @@ void Lexer::error(const char *format, ...) { - if (!global.gag) + if (mod && !global.gag) { char *p = loc.toChars(); if (*p) @@ -249,7 +252,7 @@ void Lexer::error(Loc loc, const char *format, ...) { - if (!global.gag) + if (mod && !global.gag) { char *p = loc.toChars(); if (*p) @@ -467,13 +470,13 @@ sprintf(timestamp, "%.24s", p); } - if (id == Id::FILE) + if (mod && id == Id::FILE) { t->value = TOKstring; t->ustring = (unsigned char *)(loc.filename ? loc.filename : mod->ident->toChars()); goto Llen; } - else if (id == Id::LINE) + else if (mod && id == Id::LINE) { t->value = TOKint64v; t->uns64value = loc.linnum; @@ -557,7 +560,12 @@ if (p[-2] == '*' && p - 3 != t->ptr) break; } - if (doDocComment && t->ptr[2] == '*' && p - 4 != t->ptr) + if (commentToken) + { + t->value = TOKcomment; + return; + } + else if (doDocComment && t->ptr[2] == '*' && p - 4 != t->ptr) { // if /** but not /**/ getDocComment(t, lastLine == linnum); } @@ -579,6 +587,12 @@ case 0: case 0x1A: + if (commentToken) + { + p = end; + t->value = TOKcomment; + return; + } if (doDocComment && t->ptr[2] == '/') getDocComment(t, lastLine == linnum); p = end; @@ -596,6 +610,13 @@ break; } + if (commentToken) + { + p++; + loc.linnum++; + t->value = TOKcomment; + return; + } if (doDocComment && t->ptr[2] == '/') getDocComment(t, lastLine == linnum); @@ -661,6 +682,11 @@ } break; } + if (commentToken) + { + t->value = TOKcomment; + return; + } if (doDocComment && t->ptr[2] == '+' && p - 4 != t->ptr) { // if /++ but not /++/ getDocComment(t, lastLine == linnum); @@ -1998,7 +2024,7 @@ continue; // skip white space case '_': - if (memcmp(p, "__FILE__", 8) == 0) + if (mod && memcmp(p, "__FILE__", 8) == 0) { p += 8; filespec = mem.strdup(loc.filename ? loc.filename : mod->ident->toChars()); @@ -2369,6 +2395,16 @@ { "version", TOKversion }, }; +int Token::isKeyword() +{ + for (unsigned u = 0; u < sizeof(keywords) / sizeof(keywords[0]); u++) + { + if (keywords[u].value == value) + return 1; + } + return 0; +} + void Lexer::initKeywords() { StringValue *sv; unsigned u; diff -uNr dmd-0.134/dmd/src/dmd/lexer.h dmd-0.135/dmd/src/dmd/lexer.h --- dmd-0.134/dmd/src/dmd/lexer.h 2005-09-13 02:50:00.000000000 +0200 +++ dmd-0.135/dmd/src/dmd/lexer.h 2005-09-29 20:25:18.000000000 +0200 @@ -65,7 +65,7 @@ TOKpragma, TOKdsymbol, TOKtypeid, TOKuadd, TOKiftype, TOKremove, - TOKnewanonclass, + TOKnewanonclass, TOKcomment, // Operators TOKlt, TOKgt, @@ -203,12 +203,14 @@ unsigned len; unsigned char postfix; // 'c', 'w', 'd' }; + Identifier *ident; }; static char *tochars[TOKMAX]; static void *operator new(size_t sz); + int isKeyword(); void print(); char *toChars(); static char *toChars(enum TOK); @@ -229,8 +231,11 @@ Module *mod; int doDocComment; // collect doc comment information int anyToken; // !=0 means seen at least one token + int commentToken; // !=0 means comments are TOKcomment's - Lexer(Module *mod, unsigned char *base, unsigned length, int doDocComment); + Lexer(Module *mod, + unsigned char *base, unsigned begoffset, unsigned endoffset, + int doDocComment, int commentToken); static void initKeywords(); static Identifier *idPool(const char *s); diff -uNr dmd-0.134/dmd/src/dmd/macro.c dmd-0.135/dmd/src/dmd/macro.c --- dmd-0.134/dmd/src/dmd/macro.c 2005-09-27 02:07:16.000000000 +0200 +++ dmd-0.135/dmd/src/dmd/macro.c 2005-10-02 13:11:34.000000000 +0200 @@ -172,7 +172,7 @@ { if (c == instring) instring = 0; - else + else if (!instring) instring = c; } continue; diff -uNr dmd-0.134/dmd/src/dmd/mars.c dmd-0.135/dmd/src/dmd/mars.c --- dmd-0.134/dmd/src/dmd/mars.c 2005-09-25 12:47:26.000000000 +0200 +++ dmd-0.135/dmd/src/dmd/mars.c 2005-10-01 23:10:04.000000000 +0200 @@ -51,7 +51,7 @@ copyright = "Copyright (c) 1999-2005 by Digital Mars"; written = "written by Walter Bright"; - version = "v0.134"; + version = "v0.135"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); @@ -575,6 +575,24 @@ m->deleteObjFile(); m->read(0); m->parse(); + if (m->isDocFile) + { + m->gendocfile(); + + // Remove m from list of modules + modules.remove(i); + i--; + + // Remove m's object file from list of object files + for (int j = 0; j < global.params.objfiles->dim; j++) + { + if (m->objfile->name->str == global.params.objfiles->data[j]) + { + global.params.objfiles->remove(j); + break; + } + } + } } if (global.errors) fatal(); diff -uNr dmd-0.134/dmd/src/dmd/module.c dmd-0.135/dmd/src/dmd/module.c --- dmd-0.134/dmd/src/dmd/module.c 2005-09-21 02:16:36.000000000 +0200 +++ dmd-0.135/dmd/src/dmd/module.c 2005-10-02 00:29:36.000000000 +0200 @@ -50,6 +50,7 @@ errors = 0; members = NULL; isHtml = 0; + isDocFile = 0; needmoduleinfo = 0; insearch = 0; searchCacheIdent = NULL; @@ -413,6 +414,15 @@ } } + /* If it starts with the string "Ddoc", then it's a documentation + * source file. + */ + if (buflen >= 4 && memcmp(buf, "Ddoc", 4) == 0) + { + comment = buf + 4; + isDocFile = 1; + return; + } if (isHtml) { OutBuffer *dbuf = new OutBuffer(); diff -uNr dmd-0.134/dmd/src/dmd/module.h dmd-0.135/dmd/src/dmd/module.h --- dmd-0.134/dmd/src/dmd/module.h 2005-09-14 19:35:16.000000000 +0200 +++ dmd-0.135/dmd/src/dmd/module.h 2005-10-01 22:50:18.000000000 +0200 @@ -54,6 +54,7 @@ File *docfile; // output documentation file unsigned errors; // if any errors in file int isHtml; // if it is an HTML file + int isDocFile; // if it is a documentation input file, not D source int needmoduleinfo; int insearch; diff -uNr dmd-0.134/dmd/src/dmd/parse.c dmd-0.135/dmd/src/dmd/parse.c --- dmd-0.134/dmd/src/dmd/parse.c 2005-09-18 01:21:42.000000000 +0200 +++ dmd-0.135/dmd/src/dmd/parse.c 2005-09-29 19:43:58.000000000 +0200 @@ -71,7 +71,7 @@ Parser::Parser(Module *module, unsigned char *base, unsigned length, int doDocComment) - : Lexer(module, base, length, doDocComment) + : Lexer(module, base, 0, length, doDocComment, 0) { //printf("Parser::Parser()\n"); md = NULL; diff -uNr dmd-0.134/dmd/src/dmd/root.c dmd-0.135/dmd/src/dmd/root.c --- dmd-0.134/dmd/src/dmd/root.c 2005-09-23 01:26:46.000000000 +0200 +++ dmd-0.135/dmd/src/dmd/root.c 2005-10-02 11:11:12.000000000 +0200 @@ -884,7 +884,7 @@ len = size; // Always store a wchar ^Z past end of buffer so scanner has a sentinel - buffer[size] = 0x1A; + buffer[size] = 0; // ^Z is obsolete, use 0 buffer[size + 1] = 0; return 0; @@ -939,7 +939,7 @@ len = size; // Always store a wchar ^Z past end of buffer so scanner has a sentinel - buffer[size] = 0x1A; + buffer[size] = 0; // ^Z is obsolete, use 0 buffer[size + 1] = 0; return 0; @@ -1661,10 +1661,15 @@ this->offset += nbytes; } -void OutBuffer::insert(unsigned offset, const void *p, unsigned nbytes) +/**************************************** + * Returns: offset + nbytes + */ + +unsigned OutBuffer::insert(unsigned offset, const void *p, unsigned nbytes) { spread(offset, nbytes); memmove(data + offset, p, nbytes); + return offset + nbytes; } void OutBuffer::remove(unsigned offset, unsigned nbytes) diff -uNr dmd-0.134/dmd/src/dmd/root.h dmd-0.135/dmd/src/dmd/root.h --- dmd-0.134/dmd/src/dmd/root.h 2005-09-23 01:26:46.000000000 +0200 +++ dmd-0.135/dmd/src/dmd/root.h 2005-10-01 13:21:10.000000000 +0200 @@ -286,7 +286,7 @@ void bracket(char left, char right); unsigned OutBuffer::bracket(unsigned i, char *left, unsigned j, char *right); void spread(unsigned offset, unsigned nbytes); - void insert(unsigned offset, const void *data, unsigned nbytes); + unsigned insert(unsigned offset, const void *data, unsigned nbytes); void remove(unsigned offset, unsigned nbytes); char *toChars(); char *extractString(); diff -uNr dmd-0.134/dmd/src/phobos/std/date.d dmd-0.135/dmd/src/phobos/std/date.d --- dmd-0.134/dmd/src/phobos/std/date.d 2005-09-28 23:21:32.000000000 +0200 +++ dmd-0.135/dmd/src/phobos/std/date.d 2005-10-03 13:02:50.000000000 +0200 @@ -1,5 +1,13 @@ -// Copyright (c) 1999-2004 by Digital Mars +/** + * Dates are represented in several formats. The date implementation revolves + * around a central type, d_time, from which other formats are converted to and + * from. + * Macros: + * WIKI = StdDate + */ + +// Copyright (c) 1999-2005 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com @@ -9,10 +17,22 @@ private import std.stdio; private import std.dateparse; +/** + * d_time is a signed arithmetic type giving the time elapsed since January 1, + * 1970. + * Negative values are for dates preceding 1970. The time unit used is Ticks. + * Ticks are milliseconds or smaller intervals. + * + * The usual arithmetic operations can be performed on d_time, such as adding, + * subtracting, etc. Elapsed time in Ticks can be computed by subtracting a + * starting d_time from an ending d_time. + */ alias long d_time; -//typedef double d_time; -d_time d_time_nan = long.min; //double.nan; +/** + * A value for d_time that does not represent a valid time. + */ +d_time d_time_nan = long.min; struct Date { @@ -43,7 +63,7 @@ msPerHour = 60 * msPerMinute, msPerDay = 86400000, TicksPerMs = 1, - TicksPerSecond = 1000, + TicksPerSecond = 1000, /// Will be at least 1000 TicksPerMinute = TicksPerSecond * 60, TicksPerHour = TicksPerMinute * 60, TicksPerDay = TicksPerHour * 24, @@ -55,13 +75,11 @@ const char[] daystr = "SunMonTueWedThuFriSat"; const char[] monstr = "JanFebMarAprMayJunJulAugSepOctNovDec"; -static int mdays[12] = [ 0,31,59,90,120,151,181,212,243,273,304,334 ]; +int mdays[12] = [ 0,31,59,90,120,151,181,212,243,273,304,334 ]; /******************************** - * Compute ISO 8601 week based year. - * Week 1 is first week with Jan 4 in it. - * Monday is start of week. - * Weeks are 1..53 + * Compute year and week [1..53] from t. The ISO 8601 week 1 is the first week + * of the year that includes January 4. Monday is the first day of the week. */ void toISO8601YearWeek(d_time t, out int year, out int week) @@ -118,7 +136,7 @@ week = (yday - ydaybeg) / 7 + 1; } -/************************************ +/* *********************************** * Divide time by divisor. Always round down, even if d is negative. */ @@ -323,14 +341,18 @@ return w; } -// Convert from UTC to local time +/*********************************** + * Convert from UTC to local time. + */ d_time UTCtoLocalTime(d_time t) { return t + LocalTZA + DaylightSavingTA(t); } -// Convert from local time to UTC +/*********************************** + * Convert from local time to UTC. + */ d_time LocalTimetoUTC(d_time t) { @@ -407,6 +429,25 @@ return toInteger(time); } +/************************************* + * Converts UTC time into a text string of the form: + * "Www Mmm dd hh:mm:ss GMT+-TZ yyyy". + * For example, "Tue Apr 02 02:04:57 GMT-0800 1996". + * If time is invalid, i.e. is d_time_nan, + * the string "Invalid date" is returned. + * + * Example: + * ------------------------------------ + d_time lNow; + char[] lNowString; + + // Grab the date and time relative to UTC + lNow = std.date.getUTCtime(); + // Convert this into the local date and time for display. + lNowString = std.date.toString(lNow); + * ------------------------------------ + */ + char[] toString(d_time time) { d_time t; @@ -455,6 +496,11 @@ return buffer[0 .. len]; } +/*********************************** + * Converts t into a text string of the form: "Www, dd Mmm yyyy hh:mm:ss UTC". + * If t is invalid, "Invalid date" is returned. + */ + char[] toUTCString(d_time t) { // Years are supposed to be -285616 .. 285616, or 7 digits @@ -477,6 +523,12 @@ return buffer[0 .. len]; } +/************************************ + * Converts the date portion of time into a text string of the form: "Www Mmm dd + * yyyy", for example, "Tue Apr 02 1996". + * If time is invalid, "Invalid date" is returned. + */ + char[] toDateString(d_time time) { d_time t; @@ -507,6 +559,12 @@ return buffer[0 .. len]; } +/****************************************** + * Converts the time portion of t into a text string of the form: "hh:mm:ss + * GMT+-TZ", for example, "02:04:57 GMT-0800". + * If t is invalid, "Invalid date" is returned. + */ + char[] toTimeString(d_time time) { d_time t; @@ -550,6 +608,12 @@ return buffer[0 .. len]; } + +/****************************************** + * Parses s as a textual date string, and returns it as a d_time. + * If the string is not a valid date, d_time_nan is returned. + */ + d_time parse(char[] s) { Date dp; @@ -596,6 +660,9 @@ private import std.c.windows.windows; //import c.time; + /****** + * Get current UTC time. + */ d_time getUTCtime() { SYSTEMTIME st; @@ -803,8 +870,15 @@ /+ ====================== DOS File Time =============================== +/ +/*** + * Type representing the DOS file date/time format. + */ typedef uint DosFileTime; +/************************************ + * Convert from DOS file date/time to d_time. + */ + d_time toDtime(DosFileTime time) { uint dt = cast(uint)time; @@ -836,6 +910,10 @@ return t; } +/**************************************** + * Convert from d_time to DOS file date/time. + */ + DosFileTime toDosFileTime(d_time t) { uint dt; diff -uNr dmd-0.134/dmd/src/phobos/std/file.d dmd-0.135/dmd/src/phobos/std/file.d --- dmd-0.134/dmd/src/phobos/std/file.d 2005-09-28 23:21:32.000000000 +0200 +++ dmd-0.135/dmd/src/phobos/std/file.d 2005-10-03 13:02:50.000000000 +0200 @@ -1,3 +1,7 @@ +/** + * Macros: + * WIKI = StdFile + */ /* * Copyright (C) 2001-2004 by Digital Mars, www.digitalmars.com @@ -46,6 +50,7 @@ } /*********************************** + * Exception thrown for file I/O errors. */ class FileException : Exception @@ -70,14 +75,12 @@ } } -/*********************************** +/* ********************************** * Basic File operations. */ /******************************************** - * Read a file. - * Returns: - * array of bytes read + * Read file name[], return array of bytes read. */ void[] read(char[] name) @@ -129,9 +132,7 @@ } /********************************************* - * Write a file. - * Returns: - * 0 success + * Write buffer[] to file name[]. */ void write(char[] name, void[] buffer) @@ -172,7 +173,7 @@ /********************************************* - * Append to a file. + * Append buffer[] to file name[]. */ void append(char[] name, void[] buffer) @@ -215,7 +216,7 @@ /*************************************************** - * Rename a file. + * Rename file from[] to to[]. */ void rename(char[] from, char[] to) @@ -232,7 +233,7 @@ /*************************************************** - * Delete a file. + * Delete file name[]. */ void remove(char[] name) @@ -249,7 +250,7 @@ /*************************************************** - * Get file size. + * Get size of file name[]. */ ulong getSize(char[] name) @@ -284,7 +285,8 @@ } /*************************************************** - * Does file (or directory) exist? + * Does file name[] (or directory) exist? + * Return 1 if it does, 0 if not. */ int exists(char[] name) @@ -301,7 +303,7 @@ } /*************************************************** - * Get file attributes. + * Get file name[] attributes. */ uint getAttributes(char[] name) @@ -320,7 +322,7 @@ } /**************************************************** - * Is name a file? + * Is name[] a file? Error if name[] doesn't exist. */ int isfile(char[] name) @@ -329,7 +331,7 @@ } /**************************************************** - * Is name a directory? + * Is name[] a directory? Error if name[] doesn't exist. */ int isdir(char[] name) @@ -338,7 +340,7 @@ } /**************************************************** - * Change directory. + * Change directory to pathname[]. */ void chdir(char[] pathname) @@ -356,7 +358,7 @@ } /**************************************************** - * Make directory. + * Make directory pathname[]. */ void mkdir(char[] pathname) @@ -374,7 +376,7 @@ } /**************************************************** - * Remove directory. + * Remove directory pathname[]. */ void rmdir(char[] pathname) @@ -433,7 +435,7 @@ } /*************************************************** - * Return contents of directory. + * Return contents of directory pathname[]. */ char[][] listdir(char[] pathname) @@ -538,7 +540,7 @@ /*************************************************** - * Copy a file. + * Copy a file from[] to[]. */ void copy(char[] from, char[] to) diff -uNr dmd-0.134/dmd/src/phobos/std/format.d dmd-0.135/dmd/src/phobos/std/format.d --- dmd-0.134/dmd/src/phobos/std/format.d 2005-09-28 23:21:32.000000000 +0200 +++ dmd-0.135/dmd/src/phobos/std/format.d 2005-10-03 13:02:50.000000000 +0200 @@ -1,5 +1,13 @@ +/** + * This module implements the workhorse functionality for string and I/O formatting. + * It's comparable to C99's vsprintf(). + * + * Macros: + * WIKI = StdFormat + */ + /* - * Copyright (C) 2004 by Digital Mars, www.digitalmars.com + * 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 @@ -50,6 +58,25 @@ extern (C) int snprintf(char* s, size_t n, char* format, ...); } +/********************************************************************** + * Signals a mismatch between a format and its corresponding argument. + */ +class FormatError : Error +{ + private: + + this() + { + super("std.format"); + } + + this(char[] msg) + { + super("std.format " ~ msg); + } +} + + enum Mangle : char { Tvoid = 'v', @@ -150,8 +177,261 @@ } /************************************ - * Convert arguments to tchar's according to format strings and feed to putc(). - * This is the core workhorse routine for all the various formatters. + * Interprets variadic argument list pointed to by argptr whose types are given + * by arguments[], formats them according to embedded format strings in the + * variadic argument list, and sends the resulting characters to putc. + * + * The variadic arguments are consumed in order. + * Each is formatted into a sequence of chars, using the default format + * specification for its type, and the + * characters are sequentially passed to putc. + * If a char[], wchar[], or dchar[] + * argument is encountered, it is interpreted as a format string. As many + * arguments as specified in the format string are consumed and formatted + * according to the format specifications in that string and passed to putc. If + * there are too few remaining arguments, a FormatError is thrown. If there are + * more remaining arguments than needed by the format specification, the default + * processing of arguments resumes until they are all consumed. + * + * Params: + * putc = Output is sent do this delegate, character by character. + * arguments = Array of TypeInfo's, one for each argument to be formatted. + * argptr = Points to variadic argument list. + * + * Throws: + * Mismatched arguments and formats result in a FormatError being thrown. + * + * Format_String: + * $(I Format strings) + * consist of characters interspersed with + * $(I format specifications). Characters are simply copied + * to the output (such as putc) after any necessary conversion + * to the corresponding UTF-8 sequence. + * + * A $(I format specification) starts with a '%' character, + * and has the following grammar: + +
+$(I FormatSpecification):
+    $(B '%%')
+    $(B '%') $(I Flags) $(I Width) $(I Precision) $(I FormatChar)
+
+$(I Flags):
+    $(I empty)
+    $(B '-') $(I Flags)
+    $(B '+') $(I Flags)
+    $(B '#') $(I Flags)
+    $(B '0') $(I Flags)
+    $(B ' ') $(I Flags)
+
+$(I Width):
+    $(I empty)
+    $(I Integer)
+    $(B '*')
+
+$(I Precision):
+    $(I empty)
+    $(B '.')
+    $(B '.') $(I Integer)
+    $(B '.*')
+
+$(I Integer):
+    $(I Digit)
+    $(I Digit) $(I Integer)
+
+$(I Digit):
+    $(B '0')
+    $(B '1')
+    $(B '2')
+    $(B '3')
+    $(B '4')
+    $(B '5')
+    $(B '6')
+    $(B '7')
+    $(B '8')
+    $(B '9')
+
+$(I FormatChar):
+    $(B 's')
+    $(B 'b')
+    $(B 'd')
+    $(B 'o')
+    $(B 'x')
+    $(B 'X')
+    $(B 'e')
+    $(B 'E')
+    $(B 'f')
+    $(B 'F')
+    $(B 'g')
+    $(B 'G')
+    $(B 'a')
+    $(B 'A')
+
+
+
$(I Flags) +
+
$(B '-') +
+ Left justify the result in the field. + It overrides any $(B 0) flag. + +
$(B '+') +
Prefix positive numbers in a signed conversion with a $(B +). + It overrides any $(I space) flag. + +
$(B '#') +
Use alternative formatting: +
+
For $(B 'o'): +
Add to precision as necessary so that the first digit + of the octal formatting is a '0', even if both the argument + and the $(I Precision) are zero. +
For $(B 'x') ($(B 'X')): +
If non-zero, prefix result with $(B 0x) ($(B 0X)). +
For floating point formatting: +
Always insert the decimal point. +
For $(B 'g') ($(B 'G')): +
Do not elide trailing zeros. +
+ +
$(B '0') +
For integer and floating point formatting when not nan or + infinity, use leading zeros + to pad rather than spaces. + Ignore if there's a $(I Precision). + +
$(B ' ') +
Prefix positive numbers in a signed conversion with a space. +
+ +
$(I Width) +
+ Specifies the minimum field width. + If the width is a $(B *), the next argument, which must be + of type $(B int), is taken as the width. + If the width is negative, it is as if the $(B -) was given + as a $(I Flags) character. + +
$(I Precision) +
Gives the precision for numeric conversions. + If the precision is a $(B *), the next argument, which must be + of type $(B int), is taken as the precision. If it is negative, + it is as if there was no $(I Precision). + +
$(I FormatChar) +
+
+
$(B 's') +
The corresponding argument is formatted in a manner consistent + with its type: +
+
$(B bit) +
The result is 'true' or 'false'. +
integral types +
The $(B %d) format is used. +
floating point types +
The $(B %g) format is used. +
string types +
The result is the string converted to UTF-8. + A $(I Precision) specifies the maximum number of characters + to use in the result. +
classes derived from $(B Object) +
The result is the string returned from the class instance's + $(B .toString()) method. + A $(I Precision) specifies the maximum number of characters + to use in the result. +
non-string static and dynamic arrays +
The result is [s0, s1, ...] + where sk is the kth element + formatted with the default format. +
+ +
$(B 'b','d','o','x','X') +
The corresponding argument must be an integral type + and is formatted as an integer. If the argument is a signed type + and the $(I FormatChar) is $(B d) it is converted to + a signed string of characters, otherwise it is treated as + unsigned. An argument of type $(B bit) is formatted as '1' + or '0'. The base used is binary for $(B b), octal for $(B o), + decimal + for $(B d), and hexadecimal for $(B x) or $(B X). + $(B x) formats using lower case letters, $(B X) uppercase. + If there are fewer resulting digits than the $(I Precision), + leading zeros are used as necessary. + If the $(I Precision) is 0 and the number is 0, no digits + result. + +
$(B 'e','E') +
A floating point number is formatted as one digit before + the decimal point, $(I Precision) digits after, the $(I FormatChar), + ±, followed by at least a two digit exponent: $(I d.dddddd)e$(I ±dd). + If there is no $(I Precision), six + digits are generated after the decimal point. + If the $(I Precision) is 0, no decimal point is generated. + +
$(B 'f','F') +
A floating point number is formatted in decimal notation. + The $(I Precision) specifies the number of digits generated + after the decimal point. It defaults to six. At least one digit + is generated before the decimal point. If the $(I Precision) + is zero, no decimal point is generated. + +
$(B 'g','G') +
A floating point number is formatted in either $(B e) or + $(B f) format for $(B g); $(B E) or $(B F) format for + $(B G). + The $(B f) format is used if the exponent for an $(B e) format + is greater than -5 and less than the $(I Precision). + The $(I Precision) specifies the number of significant + digits, and defaults to one. + Trailing zeros are elided after the decimal point, if the fractional + part is zero then no decimal point is generated. + +
$(B 'a','A') +
A floating point number is formatted in hexadecimal + exponential notation 0x$(I h.hhhhhh)p$(I ±d). + There is one hexadecimal digit before the decimal point, and as + many after as specified by the $(I Precision). + If the $(I Precision) is zero, no decimal point is generated. + If there is no $(I Precision), as many hexadecimal digits as + necessary to exactly represent the mantissa are generated. + The exponent is written in as few digits as possible, + but at least one, is in decimal, and represents a power of 2 as in + $(I h.hhhhhh)*2$(I ±d). + The exponent for zero is zero. + The hexadecimal digits, x and p are in upper case if the + $(I FormatChar) is upper case. +
+ + Floating point NaN's are formatted as $(B nan) if the + $(I FormatChar) is lower case, or $(B NAN) if upper. + Floating point infinities are formatted as $(B inf) or + $(B infinity) if the + $(I FormatChar) is lower case, or $(B INF) or $(B INFINITY) if upper. +
+ +Example: + +------------------------- +import std.c.stdio; +import std.format; + +void formattedPrint(...) +{ + void putc(char c) + { + fputc(c, stdout); + } + + std.format.doFormat(&putc, _arguments, _argptr); +} + +... + +int x = 27; +// prints 'The answer is 27:6' +formattedPrint("The answer is %s:", x, 6); +------------------------ */ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr) @@ -780,22 +1060,6 @@ throw new FormatError(); } - -class FormatError : Error -{ - private: - - this() - { - super("std.format"); - } - - this(char[] msg) - { - super("std.format " ~ msg); - } -} - /* ======================== Unit Tests ====================================== */ unittest diff -uNr dmd-0.134/dmd/src/phobos/std/random.d dmd-0.135/dmd/src/phobos/std/random.d --- dmd-0.134/dmd/src/phobos/std/random.d 2005-09-28 23:21:32.000000000 +0200 +++ dmd-0.135/dmd/src/phobos/std/random.d 2005-10-03 13:02:50.000000000 +0200 @@ -1,3 +1,7 @@ +/** + * Macros: + * WIKI = StdRandom + */ // random.d // www.digitalmars.com @@ -24,11 +28,26 @@ private uint seed; // starting seed private uint index; // ith random number -void rand_seed(uint s, uint i) -{ - seed = s; - index = i; -} +/** + * The random number generator is seeded at program startup with a random value. + This ensures that each program generates a different sequence of random + numbers. To generate a repeatable sequence, use rand_seed() to start the + sequence. seed and index start it, and each successive value increments index. + This means that the $(I n)th random number of the sequence can be directly + generated + by passing index + $(I n) to rand_seed(). + */ + +void rand_seed(uint seed, uint index) +{ + .seed = seed; + .index = index; +} + +/** + * Get the next random number in sequence. + * BUGS: shares a global single state, not multithreaded + */ uint rand() { diff -uNr dmd-0.134/dmd/src/phobos/std.ddoc dmd-0.135/dmd/src/phobos/std.ddoc --- dmd-0.134/dmd/src/phobos/std.ddoc 2005-09-28 23:21:32.000000000 +0200 +++ dmd-0.135/dmd/src/phobos/std.ddoc 2005-10-03 13:02:50.000000000 +0200 @@ -12,7 +12,7 @@ Digital Mars - The D Programming Language - $(TITLE) - + @@ -99,9 +99,7 @@

$(TITLE)

-
$(BODY) -
@@ -132,4 +130,12 @@ -RED = $0 +RED = $0 +GREEN = $0 +BLUE = $0 +YELLOW = $0 +BLACK = $0 +WHITE = $0 + +RPAREN = ) +LPAREN = (