\n");
+
+ p++;
+
+ Lcont:
+ continue;
+
+ Lskipline:
+ // Ignore this line
+ while (*p++ != '\n')
+ ;
+ }
+ buf->writestring("
\n");
+}
+
+/************************************************
+ * Parse macros out of Macros: section.
+ * Macros are of the form:
+ * name1 = value1
+ *
+ * name2 = value2
+ */
+
+void DocComment::doMacros(Macro **pmacrotable)
+{
+ unsigned char *p = macros->body;
+ unsigned len = macros->bodylen;
+ unsigned char *pend = p + len;
+
+ unsigned char *tempstart;
+ unsigned templen;
+
+ unsigned char *namestart;
+ unsigned namelen = 0; // !=0 if line continuation
+
+ unsigned char *textstart;
+ unsigned textlen;
+
+ while (p < pend)
+ {
+ // Skip to start of macro
+ for (; 1; p++)
+ {
+ switch (*p)
+ {
+ case ' ':
+ case '\t':
+ continue;
+
+ case '\n':
+ p++;
+ goto Lcont;
+
+ default:
+ if (!(isalpha(*p) || *p == '_'))
+ {
+ if (namelen)
+ goto Ltext; // continuation of prev macro
+ goto Lskipline;
+ }
+ break;
+ }
+ break;
+ }
+ tempstart = p;
+
+ while (isalnum(*p) || *p == '_')
+ p++;
+ templen = p - tempstart;
+
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ if (*p != '=')
+ { if (namelen)
+ goto Ltext; // continuation of prev macro
+ goto Lskipline;
+ }
+ p++;
+
+ namestart = tempstart;
+ namelen = templen;
+
+ while (*p == ' ' || *p == '\t')
+ p++;
+ textstart = p;
+
+ Ltext:
+ while (*p != '\n')
+ p++;
+ textlen = p - textstart;
+
+ //printf("macro '%.*s' = '%.*s'\n", namelen, namestart, textlen, textstart);
+ Macro::define(pmacrotable, namestart, namelen, textstart, textlen);
+
+ p++;
+ //printf("p = %p, pend = %p\n", p, pend);
+
+ Lcont:
+ continue;
+
+ Lskipline:
+ // Ignore this line
+ while (*p++ != '\n')
+ ;
+ }
+}
+
+/******************************************
+ * Compare 0-terminated string with length terminated string.
+ * Return < 0, ==0, > 0
+ */
+
+int cmp(char *stringz, void *s, size_t slen)
+{
+ size_t len1 = strlen(stringz);
+
+ if (len1 != slen)
+ return len1 - slen;
+ return memcmp(stringz, s, slen);
+}
+
+int icmp(char *stringz, void *s, size_t slen)
+{
+ size_t len1 = strlen(stringz);
+
+ if (len1 != slen)
+ return len1 - slen;
+ return memicmp(stringz, (char *)s, slen);
+}
+
+/*****************************************
+ * Return !=0 if comment consists entirely of "ditto".
+ */
+
+int isDitto(unsigned char *comment)
+{
+ if (comment)
+ {
+ unsigned char *p = skipwhitespace(comment);
+
+ if (memicmp((char *)p, "ditto", 5) == 0 && *skipwhitespace(p + 5) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+/**********************************************
+ * Skip white space.
+ */
+
+unsigned char *skipwhitespace(unsigned char *p)
+{
+ for (; 1; p++)
+ { switch (*p)
+ {
+ case ' ':
+ case '\t':
+ case '\n':
+ continue;
+ }
+ break;
+ }
+ return p;
+}
+
+
+/************************************************
+ * Scan forward to one of:
+ * start of identifier
+ * beginning of next line
+ * end of buf
+ */
+
+unsigned skiptoident(OutBuffer *buf, unsigned i)
+{
+ for (; i < buf->offset; i++)
+ {
+ // BUG: handle unicode alpha's
+ unsigned char c = buf->data[i];
+ if (isalpha(c) || c == '_')
+ break;
+ if (c == '\n')
+ break;
+ }
+ return i;
+}
+
+/************************************************
+ * Scan forward past end of identifier.
+ */
+
+unsigned skippastident(OutBuffer *buf, unsigned i)
+{
+ for (; i < buf->offset; i++)
+ {
+ // BUG: handle unicode alpha's
+ unsigned char c = buf->data[i];
+ if (!(isalnum(c) || c == '_'))
+ break;
+ }
+ return i;
+}
+
+
+/****************************************************
+ */
+
+int isKeyword(unsigned char *p, unsigned len)
+{
+ static char *table[] = { "true", "false", "null" };
+
+ for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++)
+ {
+ if (cmp(table[i], p, len) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+/****************************************************
+ */
+
+Argument *isFunctionParameter(Dsymbol *s, unsigned char *p, unsigned len)
+{
+ FuncDeclaration *f = s->isFuncDeclaration();
+
+ /* f->type may be NULL for template members.
+ */
+ if (f && f->type)
+ {
+ TypeFunction *tf = (TypeFunction *)f->type;
+
+ if (tf->arguments)
+ {
+ for (int k = 0; k < tf->arguments->dim; k++)
+ { Argument *arg = (Argument *)tf->arguments->data[k];
+
+ if (arg->ident && cmp(arg->ident->toChars(), p, len) == 0)
+ {
+ return arg;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+/**************************************************
+ * Highlight text section.
+ */
+
+void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
+{
+ //printf("highlightText()\n");
+ char *sid = s->ident->toChars();
+ FuncDeclaration *f = s->isFuncDeclaration();
+ unsigned char *p;
+
+ int leadingBlank = 1;
+ int inCode = 0;
+ int inComment = 0; // in comment
+ unsigned iCodeStart; // start of code section
+ unsigned iLineStart = offset;
+
+ for (unsigned i = offset; i < buf->offset; i++)
+ { unsigned char c = buf->data[i];
+
+ Lcont:
+ switch (c)
+ {
+ case ' ':
+ case '\t':
+ break;
+
+ case '\n':
+ if (i == iLineStart) // if "\n\n"
+ { buf->insert(i, "\n
", 8);
+ i += 8; // point at last '>'
+ }
+ leadingBlank = 1;
+ iLineStart = i + 1;
+ break;
+
+ case '<':
+ leadingBlank = 0;
+ if (inCode)
+ break;
+ p = &buf->data[i];
+
+ // Skip over comments
+ if (p[1] == '!' && p[2] == '-' && p[3] == '-')
+ { unsigned j = i + 4;
+ p += 4;
+ while (1)
+ {
+ if (j == buf->offset)
+ goto L1;
+ if (p[0] == '-' && p[1] == '-' && p[2] == '>')
+ {
+ i = j + 2; // place on closing '>'
+ break;
+ }
+ j++;
+ p++;
+ }
+ break;
+ }
+
+ // Skip over HTML tag
+ if (isalpha(p[1]) || (p[1] == '/' && isalpha(p[2])))
+ { unsigned j = i + 2;
+ p += 2;
+ while (1)
+ {
+ if (j == buf->offset)
+ goto L1;
+ if (p[0] == '>')
+ {
+ i = j; // place on closing '>'
+ break;
+ }
+ j++;
+ p++;
+ }
+ break;
+ }
+
+ L1:
+ // Replace '<' with < character entity
+ buf->remove(i, 1);
+ buf->insert(i, "<", 4);
+ i += 3; // point to ';'
+ break;
+
+ case '>':
+ leadingBlank = 0;
+ if (inCode)
+ break;
+ buf->remove(i, 1);
+ buf->insert(i, ">", 4);
+ i += 3; // point to ';'
+ break;
+
+ case '&':
+ leadingBlank = 0;
+ if (inCode)
+ break;
+ p = &buf->data[i];
+ if (p[1] == '#' || isalpha(p[1]))
+ break; // already a character entity
+ buf->remove(i, 1);
+ buf->insert(i, "&", 5);
+ i += 4; // point to ';'
+ break;
+
+ case '-':
+ /* A line beginning with --- delimits a code section.
+ * inCode tells us if it is start or end of a code section.
+ */
+ if (leadingBlank)
+ { int istart = i;
+
+ leadingBlank = 0;
+ while (1)
+ {
+ ++i;
+ assert(i < buf->offset);
+ c = buf->data[i];
+ if (c != '-')
+ break;
+ }
+ if (c != '\n' || i - istart < 3)
+ goto Lcont;
+
+ // We have the start/end of a code section
+
+ // Remove the entire --- line, including blanks and \n
+ buf->remove(iLineStart, i - iLineStart + 1); // remove '-----\n'
+ i = iLineStart;
+
+ if (inCode)
+ {
+ inCode = 0;
+ // The code section is from iCodeStart to i
+ OutBuffer codebuf;
+
+ codebuf.write(buf->data + iCodeStart, i - iCodeStart);
+ highlightCode(sc, s, &codebuf, 0);
+ buf->remove(iCodeStart, i - iCodeStart);
+ buf->insert(iCodeStart, codebuf.data, codebuf.offset);
+ i = iCodeStart + codebuf.offset;
+ buf->insert(i, "\n", 7);
+ i += 5; // place i on >
+ }
+ else
+ { static char pre[] = "
\n";
+
+ inCode = 1;
+ buf->insert(i, pre, sizeof(pre) - 1);
+ i += sizeof(pre) - 2; // place i on >
+ iCodeStart = i + 2;
+ }
+ }
+ break;
+
+ default:
+ leadingBlank = 0;
+ if (!inCode && (isalpha(c) || c == '_'))
+ { unsigned j;
+
+ j = skippastident(buf, i);
+ if (j > i)
+ {
+ if (buf->data[i] == '_') // leading '_' means no highlight
+ {
+ buf->remove(i, 1);
+ i = j - 1;
+ }
+ else
+ {
+ if (cmp(sid, buf->data + i, j - i) == 0 ||
+ isKeyword(buf->data + i, j - i))
+ {
+ buf->insert(i, "", 3);
+ buf->insert(j + 3, "", 4);
+ i = j + 7 - 1;
+ break;
+ }
+ else
+ {
+ if (f && isFunctionParameter(f, buf->data + i, j - i))
+ {
+ //printf("highlighting arg '%s', i = %d, j = %d\n", arg->ident->toChars(), i, j);
+ buf->insert(i, "", 3);
+ buf->insert(j + 3, "", 4);
+ i = j + 7 - 1;
+ break;
+ }
+ }
+ i = j - 1;
+ }
+ }
+ }
+ break;
+ }
+ }
+ Ldone:
+ ;
+}
+
+/**************************************************
+ * Highlight code.
+ */
+
+void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
+{
+ char *sid = s->ident->toChars();
+ FuncDeclaration *f = s->isFuncDeclaration();
+
+ for (unsigned i = offset; i < buf->offset; i++)
+ { unsigned char c = buf->data[i];
+
+ switch (c)
+ {
+ case '<': // replace '<' with '<'
+ buf->remove(i, 1);
+ buf->insert(i, "<", 4);
+ i += 3; // point to ';'
+ break;
+
+ case '>':
+ buf->remove(i, 1);
+ buf->insert(i, ">", 4);
+ i += 3; // point to ';'
+ break;
+
+ case '&':
+ buf->remove(i, 1);
+ buf->insert(i, "&", 5);
+ i += 4; // point to ';'
+ break;
+
+ default:
+ if (isalpha(c) || c == '_')
+ { unsigned j;
+
+ j = skippastident(buf, i);
+ if (j > i)
+ {
+ if (cmp(sid, buf->data + i, j - i) == 0)
+ {
+ buf->insert(i, "", 3);
+ buf->insert(j + 3, "", 4);
+ i = j + 7 - 1;
+ break;
+ }
+ else if (f)
+ {
+ if (isFunctionParameter(f, buf->data + i, j - i))
+ {
+ //printf("highlighting arg '%s', i = %d, j = %d\n", arg->ident->toChars(), i, j);
+ buf->insert(i, "", 3);
+ buf->insert(j + 3, "", 4);
+ i = j + 7 - 1;
+ break;
+ }
+ }
+ i = j - 1;
+ }
+ }
+ break;
+ }
+ }
+}
+
diff -uNr dmd-0.131/dmd/src/dmd/doc.h dmd-0.132/dmd/src/dmd/doc.h
--- dmd-0.131/dmd/src/dmd/doc.h 1970-01-01 01:00:00.000000000 +0100
+++ dmd-0.132/dmd/src/dmd/doc.h 2005-09-17 00:37:06.000000000 +0200
@@ -0,0 +1,18 @@
+
+// Copyright (c) 1999-2005 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#ifndef DMD_DOC_H
+#define DMD_DOC_H
+
+#ifdef __DMC__
+#pragma once
+#endif /* __DMC__ */
+
+
+#endif
diff -uNr dmd-0.131/dmd/src/dmd/dsymbol.c dmd-0.132/dmd/src/dmd/dsymbol.c
--- dmd-0.131/dmd/src/dmd/dsymbol.c 2005-06-12 01:51:00.000000000 +0200
+++ dmd-0.132/dmd/src/dmd/dsymbol.c 2005-09-15 01:19:54.000000000 +0200
@@ -36,6 +36,7 @@
this->csym = NULL;
this->isym = NULL;
this->loc = 0;
+ this->comment = NULL;
}
Dsymbol::Dsymbol(Identifier *ident)
@@ -47,6 +48,7 @@
this->csym = NULL;
this->isym = NULL;
this->loc = 0;
+ this->comment = NULL;
}
int Dsymbol::equals(Object *o)
@@ -415,6 +417,22 @@
return b;
}
+
+/****************************************
+ * Add documentation comment to Dsymbol.
+ * Ignore NULL comments.
+ */
+
+void Dsymbol::addComment(unsigned char *comment)
+{
+ //if (comment)
+ //printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
+
+ if (!this->comment)
+ this->comment = comment;
+}
+
+
/********************************* ScopeDsymbol ****************************/
ScopeDsymbol::ScopeDsymbol()
diff -uNr dmd-0.131/dmd/src/dmd/dsymbol.h dmd-0.132/dmd/src/dmd/dsymbol.h
--- dmd-0.131/dmd/src/dmd/dsymbol.h 2005-07-23 10:15:42.000000000 +0200
+++ dmd-0.132/dmd/src/dmd/dsymbol.h 2005-09-19 11:18:42.000000000 +0200
@@ -81,6 +81,7 @@
Dsymbol *parent;
Symbol *csym; // symbol for code generator
Symbol *isym; // import version of csym
+ unsigned char *comment; // documentation comment for this Dsymbol
Loc loc; // where defined
Dsymbol();
@@ -111,6 +112,7 @@
virtual Dsymbol *search(Identifier *ident, int flags);
virtual int overloadInsert(Dsymbol *s);
virtual void toCBuffer(OutBuffer *buf);
+ virtual void toDocBuffer(OutBuffer *buf);
virtual unsigned size(Loc loc);
virtual int isforwardRef();
virtual void defineRef(Dsymbol *s);
@@ -130,6 +132,10 @@
virtual void addLocalClass(Array *) { }
virtual void checkCtorConstInit() { }
+ virtual void addComment(unsigned char *comment);
+ virtual void emitComment(Scope *sc);
+ void emitDitto(Scope *sc);
+
// Backend
virtual Symbol *toSymbol(); // to backend symbol
@@ -196,6 +202,8 @@
Dsymbol *nameCollision(Dsymbol *s);
char *kind();
+ void emitMemberComments(Scope *sc);
+
ScopeDsymbol *isScopeDsymbol() { return this; }
};
diff -uNr dmd-0.131/dmd/src/dmd/enum.h dmd-0.132/dmd/src/dmd/enum.h
--- dmd-0.131/dmd/src/dmd/enum.h 2005-05-09 15:51:16.000000000 +0200
+++ dmd-0.132/dmd/src/dmd/enum.h 2005-09-18 22:55:10.000000000 +0200
@@ -37,6 +37,9 @@
Type *getType();
char *kind();
+ void emitComment(Scope *sc);
+ void toDocBuffer(OutBuffer *buf);
+
EnumDeclaration *isEnumDeclaration() { return this; }
void toObjFile(); // compile to .obj file
@@ -54,6 +57,9 @@
void toCBuffer(OutBuffer *buf);
char *kind();
+ void emitComment(Scope *sc);
+ void toDocBuffer(OutBuffer *buf);
+
EnumMember *isEnumMember() { return this; }
};
diff -uNr dmd-0.131/dmd/src/dmd/lexer.c dmd-0.132/dmd/src/dmd/lexer.c
--- dmd-0.131/dmd/src/dmd/lexer.c 2005-07-19 09:47:48.000000000 +0200
+++ dmd-0.132/dmd/src/dmd/lexer.c 2005-09-15 17:06:58.000000000 +0200
@@ -79,7 +79,7 @@
}
-/******************************************************/
+/************************* Token **********************************************/
char *Token::tochars[TOKMAX];
@@ -187,13 +187,13 @@
return p;
}
-/******************************************************/
+/*************************** Lexer ********************************************/
Token *Lexer::freelist = NULL;
StringTable Lexer::stringtable;
OutBuffer Lexer::stringbuffer;
-Lexer::Lexer(Module *mod, unsigned char *base, unsigned length)
+Lexer::Lexer(Module *mod, unsigned char *base, unsigned length, int doDocComment)
: loc(mod, 1)
{
//printf("Lexer::Lexer(%p,%d)\n",base,length);
@@ -203,6 +203,8 @@
this->end = base + length;
p = base;
this->mod = mod;
+ this->doDocComment = doDocComment;
+ this->anyToken = 0;
//initKeywords();
}
@@ -307,6 +309,11 @@
void Lexer::scan(Token *t)
{
+ unsigned lastLine = loc.linnum;
+ unsigned linnum;
+
+ t->blockComment = NULL;
+ t->lineComment = NULL;
while (1)
{
t->ptr = p;
@@ -441,6 +448,7 @@
}
t->ident = id;
t->value = (enum TOK) id->value;
+ anyToken = 1;
if (*t->ptr == '_') // if special identifier token
{
static char date[11+1];
@@ -506,6 +514,7 @@
case '*':
p++;
+ linnum = loc.linnum;
while (1)
{
while (1)
@@ -548,9 +557,14 @@
if (p[-2] == '*' && p - 3 != t->ptr)
break;
}
+ if (doDocComment && t->ptr[2] == '*' && p - 4 != t->ptr)
+ { // if /** but not /**/
+ getDocComment(t, lastLine == linnum);
+ }
continue;
- case '/':
+ case '/': // do // style comments
+ linnum = loc.linnum;
while (1)
{ unsigned char c = *++p;
switch (c)
@@ -565,6 +579,8 @@
case 0:
case 0x1A:
+ if (doDocComment && t->ptr[2] == '/')
+ getDocComment(t, lastLine == linnum);
p = end;
t->value = TOKeof;
return;
@@ -579,6 +595,10 @@
}
break;
}
+
+ if (doDocComment && t->ptr[2] == '/')
+ getDocComment(t, lastLine == linnum);
+
p++;
loc.linnum++;
continue;
@@ -586,6 +606,7 @@
case '+':
{ int nest;
+ linnum = loc.linnum;
p++;
nest = 1;
while (1)
@@ -640,6 +661,10 @@
}
break;
}
+ if (doDocComment && t->ptr[2] == '+' && p - 4 != t->ptr)
+ { // if /++ but not /++/
+ getDocComment(t, lastLine == linnum);
+ }
continue;
}
}
@@ -2065,6 +2090,134 @@
return u;
}
+
+/***************************************************
+ * Parse doc comment embedded between t->ptr and p.
+ * Remove trailing blanks and tabs from lines.
+ * Replace all newlines with \n.
+ * Remove leading comment character from each line.
+ * Decide if it's a lineComment or a blockComment.
+ * Append to previous one for this token.
+ */
+
+void Lexer::getDocComment(Token *t, unsigned lineComment)
+{
+ OutBuffer buf;
+ unsigned char ct = t->ptr[2];
+ unsigned char *q = t->ptr + 3; // start of comment text
+ int linestart = 0;
+
+ unsigned char *qend = p;
+ if (ct == '*' || ct == '+')
+ qend -= 2;
+
+ /* Scan over initial row of ****'s or ++++'s or ////'s
+ */
+ for (; q < qend; q++)
+ {
+ if (*q != ct)
+ break;
+ }
+
+ for (; q < qend; q++)
+ {
+ unsigned char c = *q;
+
+ switch (c)
+ {
+ case '*':
+ case '+':
+ if (linestart && c == ct)
+ { linestart = 0;
+ /* Trim preceding whitespace up to preceding \n
+ */
+ while (buf.offset && (buf.data[buf.offset - 1] == ' ' || buf.data[buf.offset - 1] == '\t'))
+ buf.offset--;
+ continue;
+ }
+ break;
+
+ case ' ':
+ case '\t':
+ break;
+
+ case '\r':
+ if (q[1] == '\n')
+ continue; // skip the \r
+ goto Lnewline;
+
+ default:
+ if (c == 226)
+ {
+ // If LS or PS
+ if (q[1] == 128 &&
+ (q[2] == 168 || q[2] == 169))
+ {
+ q += 2;
+ goto Lnewline;
+ }
+ }
+ linestart = 0;
+ break;
+
+ Lnewline:
+ c = '\n'; // replace all newlines with \n
+ case '\n':
+ linestart = 1;
+
+ /* Trim trailing whitespace
+ */
+ while (buf.offset && (buf.data[buf.offset - 1] == ' ' || buf.data[buf.offset - 1] == '\t'))
+ buf.offset--;
+
+ break;
+ }
+ buf.writeByte(c);
+ }
+
+ // Always end with a newline
+ if (!buf.offset || buf.data[buf.offset - 1] != '\n')
+ buf.writeByte('\n');
+
+ buf.writeByte(0);
+
+ // It's a line comment if the start of the doc comment comes
+ // after other non-whitespace on the same line.
+ unsigned char** dc = (lineComment && anyToken)
+ ? &t->lineComment
+ : &t->blockComment;
+
+ // Combine with previous doc comment, if any
+ if (*dc)
+ *dc = combineComments(*dc, (unsigned char *)buf.data);
+ else
+ *dc = (unsigned char *)buf.extractData();
+}
+
+/********************************************
+ * Combine two document comments into one.
+ */
+
+unsigned char *Lexer::combineComments(unsigned char *c1, unsigned char *c2)
+{
+ unsigned char *c = c2;
+
+ if (c1)
+ { c = c1;
+ if (c2)
+ { size_t len1 = strlen((char *)c1);
+ size_t len2 = strlen((char *)c2);
+
+ c = (unsigned char *)mem.malloc(len1 + 1 + len2 + 1);
+ memcpy(c, c1, len1);
+ c[len1] = '\n';
+ memcpy(c + len1 + 1, c2, len2);
+ c[len1 + 1 + len2] = 0;
+ }
+ }
+ return c;
+}
+
/********************************************
* Create an identifier in the string table.
*/
diff -uNr dmd-0.131/dmd/src/dmd/lexer.h dmd-0.132/dmd/src/dmd/lexer.h
--- dmd-0.131/dmd/src/dmd/lexer.h 2005-07-18 10:27:38.000000000 +0200
+++ dmd-0.132/dmd/src/dmd/lexer.h 2005-09-13 02:50:00.000000000 +0200
@@ -185,6 +185,8 @@
Token *next;
unsigned char *ptr; // pointer to first character of this token within buffer
enum TOK value;
+ unsigned char *blockComment; // doc comment string prior to this token
+ unsigned char *lineComment; // doc comment for previous token
union
{
// Integers
@@ -225,8 +227,10 @@
unsigned char *p; // current character
Token token;
Module *mod;
+ int doDocComment; // collect doc comment information
+ int anyToken; // !=0 means seen at least one token
- Lexer(Module *mod, unsigned char *base, unsigned length);
+ Lexer(Module *mod, unsigned char *base, unsigned length, int doDocComment);
static void initKeywords();
static Identifier *idPool(const char *s);
@@ -247,6 +251,9 @@
void error(Loc loc, const char *format, ...);
void pragma();
unsigned decodeUTF();
+ void getDocComment(Token *t, unsigned lineComment);
+
+ static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
};
#endif /* DMD_LEXER_H */
diff -uNr dmd-0.131/dmd/src/dmd/mars.c dmd-0.132/dmd/src/dmd/mars.c
--- dmd-0.131/dmd/src/dmd/mars.c 2005-09-08 19:11:24.000000000 +0200
+++ dmd-0.132/dmd/src/dmd/mars.c 2005-09-13 03:26:32.000000000 +0200
@@ -38,6 +38,7 @@
{
mars_ext = "d";
sym_ext = "d";
+ doc_ext = "html";
#if _WIN32
obj_ext = "obj";
@@ -49,7 +50,7 @@
copyright = "Copyright (c) 1999-2005 by Digital Mars";
written = "written by Walter Bright";
- version = "v0.131";
+ version = "v0.132";
global.structalign = 8;
memset(¶ms, 0, sizeof(Param));
@@ -129,6 +130,9 @@
\n\
files.d D source files\n\
-c do not link\n\
+ -D generate documentation\n\
+ -Dddocdir write documentation file to docdir directory\n\
+ -Dffilename write documentation file to filename\n\
-d allow deprecated features\n\
-debug compile in debug code\n\
-debug=level compile in debug code <= level\n\
@@ -272,6 +276,28 @@
goto Lerror;
}
}
+ else if (p[1] == 'D')
+ { global.params.doDocComments = 1;
+ switch (p[2])
+ {
+ case 'd':
+ if (!p[3])
+ goto Lnoarg;
+ global.params.docdir = p + 3;
+ break;
+ case 'f':
+ if (!p[3])
+ goto Lnoarg;
+ global.params.docname = p + 3;
+ break;
+
+ case 0:
+ break;
+
+ default:
+ goto Lerror;
+ }
+ }
else if (strcmp(p + 1, "inline") == 0)
global.params.useInline = 1;
else if (strcmp(p + 1, "quiet") == 0)
@@ -515,7 +541,7 @@
}
id = new Identifier(name, 0);
- m = new Module((char *) files.data[i], id);
+ m = new Module((char *) files.data[i], id, global.params.doDocComments);
modules.push(m);
global.params.objfiles->push(m->objfile->name->str);
@@ -588,9 +614,14 @@
if (global.params.verbose)
printf("code %s\n", m->toChars());
m->genobjfile();
-// m->gensymfile();
if (global.errors)
m->deleteObjFile();
+ else
+ {
+ //m->gensymfile();
+ if (global.params.doDocComments)
+ m->gendocfile();
+ }
}
backend_term();
diff -uNr dmd-0.131/dmd/src/dmd/mars.h dmd-0.132/dmd/src/dmd/mars.h
--- dmd-0.131/dmd/src/dmd/mars.h 2005-05-25 21:40:40.000000000 +0200
+++ dmd-0.132/dmd/src/dmd/mars.h 2005-09-11 02:11:08.000000000 +0200
@@ -47,6 +47,10 @@
char *objdir; // .obj file output directory
char *objname; // .obj file output name
+ char doDocComments; // process embedded documentation comments
+ char *docdir; // write documentation file to docdir directory
+ char *docname; // write documentation file to docname
+
unsigned debuglevel; // debug level
Array *debugids; // debug identifiers
@@ -77,6 +81,7 @@
char *mars_ext;
char *sym_ext;
char *obj_ext;
+ char *doc_ext;
char *copyright;
char *written;
Array *path; // Array of char*'s which form the import lookup path
diff -uNr dmd-0.131/dmd/src/dmd/module.c dmd-0.132/dmd/src/dmd/module.c
--- dmd-0.131/dmd/src/dmd/module.c 2005-06-16 12:50:46.000000000 +0200
+++ dmd-0.132/dmd/src/dmd/module.c 2005-09-14 19:40:42.000000000 +0200
@@ -34,7 +34,7 @@
modules = new DsymbolTable();
}
-Module::Module(char *filename, Identifier *ident)
+Module::Module(char *filename, Identifier *ident, int doDocComment)
: Package(ident)
{
FileName *srcfilename;
@@ -42,6 +42,7 @@
FileName *hfilename;
FileName *objfilename;
FileName *symfilename;
+ FileName *docfilename;
// printf("Module::Module(filename = '%s', ident = '%s')\n", filename, ident->toChars());
this->arg = filename;
@@ -65,6 +66,7 @@
sfilename = NULL;
importedFrom = this;
srcfile = NULL;
+ docfile = NULL;
debuglevel = 0;
debugids = NULL;
@@ -73,6 +75,8 @@
versionids = NULL;
versionidsNot = NULL;
+ macrotable = NULL;
+
srcfilename = FileName::defaultExt(filename, global.mars_ext);
if (!srcfilename->equalsExt(global.mars_ext))
{
@@ -98,6 +102,30 @@
else
objfilename = FileName::forceExt(argobj, global.obj_ext);
+ if (doDocComment)
+ {
+ char *argdoc;
+ if (global.params.docname)
+ argdoc = global.params.docname;
+ else if (global.params.preservePaths)
+ argdoc = filename;
+ else
+ argdoc = FileName::name(filename);
+ if (!FileName::absolute(argdoc))
+ argdoc = FileName::combine(global.params.docdir, argdoc);
+ if (global.params.docname)
+ docfilename = new FileName(argdoc, 0);
+ else
+ docfilename = FileName::forceExt(argdoc, global.doc_ext);
+
+ if (docfilename->equals(srcfilename))
+ { error("Source file and documentation file have same name '%s'", srcfilename->toChars());
+ fatal();
+ }
+
+ docfile = new File(docfilename);
+ }
+
symfilename = FileName::forceExt(filename, global.sym_ext);
srcfile = new File(srcfilename);
@@ -108,6 +136,8 @@
void Module::deleteObjFile()
{
objfile->remove();
+ if (docfile)
+ docfile->remove();
}
Module::~Module()
@@ -150,7 +180,7 @@
filename = (char *)buf.extractData();
}
- m = new Module(filename, ident);
+ m = new Module(filename, ident, 0);
m->loc = loc;
// Find the sym file
@@ -390,7 +420,7 @@
buf = dbuf->data;
buflen = dbuf->offset;
}
- Parser p(this, buf, buflen);
+ Parser p(this, buf, buflen, docfile != NULL);
members = p.parseModule();
md = p.md;
@@ -559,6 +589,9 @@
}
}
+/****************************************************
+ */
+
void Module::gensymfile()
{
OutBuffer buf;
diff -uNr dmd-0.131/dmd/src/dmd/module.h dmd-0.132/dmd/src/dmd/module.h
--- dmd-0.131/dmd/src/dmd/module.h 2005-06-16 12:50:46.000000000 +0200
+++ dmd-0.132/dmd/src/dmd/module.h 2005-09-14 19:35:16.000000000 +0200
@@ -20,6 +20,7 @@
struct ModuleInfoDeclaration;
struct ClassDeclaration;
struct ModuleDeclaration;
+struct Macro;
// Back end
struct elem;
@@ -50,6 +51,7 @@
File *srcfile; // input source file
File *objfile; // output .obj file
File *symfile; // output symbol file
+ File *docfile; // output documentation file
unsigned errors; // if any errors in file
int isHtml; // if it is an HTML file
int needmoduleinfo;
@@ -78,8 +80,9 @@
Array *versionids; // version identifiers
Array *versionidsNot; // forward referenced version identifiers
+ Macro *macrotable; // document comment macros
- Module(char *arg, Identifier *ident);
+ Module(char *arg, Identifier *ident, int doDocComment);
~Module();
static Module *load(Loc loc, Array *packages, Identifier *ident);
@@ -93,6 +96,7 @@
void inlineScan(); // scan for functions to inline
void genobjfile();
void gensymfile();
+ void gendocfile();
int needModuleInfo();
Dsymbol *search(Identifier *ident, int flags);
void deleteObjFile();
diff -uNr dmd-0.131/dmd/src/dmd/mtype.c dmd-0.132/dmd/src/dmd/mtype.c
--- dmd-0.131/dmd/src/dmd/mtype.c 2005-07-19 10:44:06.000000000 +0200
+++ dmd-0.132/dmd/src/dmd/mtype.c 2005-09-13 16:03:12.000000000 +0200
@@ -315,7 +315,6 @@
void Type::toCBuffer2(OutBuffer *buf, Identifier *ident)
{
-// buf->prependbyte(' ');
buf->prependstring(toChars());
if (ident)
{ buf->writeByte(' ');
diff -uNr dmd-0.131/dmd/src/dmd/parse.c dmd-0.132/dmd/src/dmd/parse.c
--- dmd-0.131/dmd/src/dmd/parse.c 2005-07-18 10:32:46.000000000 +0200
+++ dmd-0.132/dmd/src/dmd/parse.c 2005-09-18 01:21:42.000000000 +0200
@@ -70,8 +70,8 @@
};
-Parser::Parser(Module *module, unsigned char *base, unsigned length)
- : Lexer(module, base, length)
+Parser::Parser(Module *module, unsigned char *base, unsigned length, int doDocComment)
+ : Lexer(module, base, length, doDocComment)
{
//printf("Parser::Parser()\n");
md = NULL;
@@ -88,6 +88,8 @@
// ModuleDeclation leads off
if (token.value == TOKmodule)
{
+ unsigned char *comment = token.blockComment;
+
nextToken();
if (token.value != TOKidentifier)
{ error("Identifier expected following module");
@@ -117,6 +119,7 @@
if (token.value != TOKsemicolon)
error("';' expected following module declaration instead of %s", token.toChars());
nextToken();
+ addComment(mod, comment);
}
}
@@ -142,11 +145,13 @@
enum PROT prot;
unsigned stc;
Condition *condition;
+ unsigned char *comment;
//printf("Parser::parseDeclDefs()\n");
decldefs = new Array();
do
{
+ comment = token.blockComment;
switch (token.value)
{
case TOKenum:
@@ -470,7 +475,9 @@
continue;
}
if (s)
- decldefs->push(s);
+ { decldefs->push(s);
+ addComment(s, comment);
+ }
} while (!once);
return decldefs;
}
@@ -961,6 +968,7 @@
//printf("enum definition\n");
e->members = new Array();
nextToken();
+ unsigned char *comment = token.blockComment;
while (token.value != TOKrcurly)
{
if (token.value == TOKidentifier)
@@ -982,6 +990,7 @@
;
else
check(TOKcomma);
+ addComment(em, comment);
}
else
{ error("enum member expected");
@@ -1933,6 +1942,7 @@
Identifier *ident;
Array *a;
enum TOK tok;
+ unsigned char *comment = token.blockComment;
//printf("parseDeclaration()\n");
switch (token.value)
@@ -1979,6 +1989,7 @@
s = (AggregateDeclaration *)parseAggregate();
s->storage_class |= storage_class;
a->push(s);
+ addComment(s, comment);
return a;
}
@@ -2023,10 +2034,12 @@
switch (token.value)
{ case TOKsemicolon:
nextToken();
+ addComment(v, comment);
break;
case TOKcomma:
nextToken();
+ addComment(v, comment);
continue;
default:
@@ -2039,7 +2052,9 @@
f = new FuncDeclaration(loc, 0, ident, storage_class, t);
a->push(f);
+ addComment(f, comment);
parseContracts(f);
+ addComment(f, NULL);
}
else
{ VarDeclaration *v;
@@ -2057,10 +2072,12 @@
switch (token.value)
{ case TOKsemicolon:
nextToken();
+ addComment(v, comment);
break;
case TOKcomma:
nextToken();
+ addComment(v, comment);
continue;
default:
@@ -4588,5 +4605,14 @@
return e;
}
+/**********************************************
+ */
+
+void Parser::addComment(Dsymbol *s, unsigned char *blockComment)
+{
+ s->addComment(combineComments(blockComment, token.lineComment));
+}
+
+
/********************************* ***************************/
diff -uNr dmd-0.131/dmd/src/dmd/parse.h dmd-0.132/dmd/src/dmd/parse.h
--- dmd-0.131/dmd/src/dmd/parse.h 2005-06-06 12:14:52.000000000 +0200
+++ dmd-0.132/dmd/src/dmd/parse.h 2005-09-12 21:42:32.000000000 +0200
@@ -47,7 +47,7 @@
Loc endloc; // set to location of last right curly
int inBrackets; // inside [] of array index or slice
- Parser(Module *module, unsigned char *base, unsigned length);
+ Parser(Module *module, unsigned char *base, unsigned length, int doDocComment);
Array *parseModule();
Array *parseDeclDefs(int once);
@@ -112,6 +112,8 @@
Array *parseArguments();
Expression *parseNewExp();
+
+ void addComment(Dsymbol *s, unsigned char *blockComment);
};
#endif /* DMD_PARSE_H */
diff -uNr dmd-0.131/dmd/src/dmd/root.c dmd-0.132/dmd/src/dmd/root.c
--- dmd-0.131/dmd/src/dmd/root.c 2004-10-28 20:08:14.000000000 +0200
+++ dmd-0.132/dmd/src/dmd/root.c 2005-09-13 19:44:52.000000000 +0200
@@ -1646,6 +1646,18 @@
this->offset += nbytes;
}
+void OutBuffer::insert(unsigned offset, const void *p, unsigned nbytes)
+{
+ spread(offset, nbytes);
+ memmove(data + offset, p, nbytes);
+}
+
+void OutBuffer::remove(unsigned offset, unsigned nbytes)
+{
+ memmove(data + offset, data + offset + nbytes, this->offset - (offset + nbytes));
+ this->offset -= nbytes;
+}
+
char *OutBuffer::toChars()
{
writeByte(0);
diff -uNr dmd-0.131/dmd/src/dmd/root.h dmd-0.132/dmd/src/dmd/root.h
--- dmd-0.131/dmd/src/dmd/root.h 2004-03-27 00:11:52.000000000 +0100
+++ dmd-0.132/dmd/src/dmd/root.h 2005-09-13 19:28:14.000000000 +0200
@@ -285,6 +285,8 @@
#endif
void bracket(char left, char right);
void spread(unsigned offset, unsigned nbytes);
+ void insert(unsigned offset, const void *data, unsigned nbytes);
+ void remove(unsigned offset, unsigned nbytes);
char *toChars();
char *extractString();
};
diff -uNr dmd-0.131/dmd/src/dmd/scope.c dmd-0.132/dmd/src/dmd/scope.c
--- dmd-0.131/dmd/src/dmd/scope.c 2005-05-26 17:18:50.000000000 +0200
+++ dmd-0.132/dmd/src/dmd/scope.c 2005-09-13 15:14:00.000000000 +0200
@@ -65,6 +65,9 @@
this->callSuper = 0;
this->flags = 0;
this->anonAgg = NULL;
+ this->lastdc = NULL;
+ this->lastoffset = 0;
+ this->docbuf = NULL;
}
Scope::Scope(Scope *enclosing)
@@ -93,6 +96,9 @@
this->callSuper = enclosing->callSuper;
this->flags = 0;
this->anonAgg = NULL;
+ this->lastdc = NULL;
+ this->lastoffset = 0;
+ this->docbuf = enclosing->docbuf;
assert(this != enclosing);
}
diff -uNr dmd-0.131/dmd/src/dmd/scope.h dmd-0.132/dmd/src/dmd/scope.h
--- dmd-0.131/dmd/src/dmd/scope.h 2005-07-19 15:21:02.000000000 +0200
+++ dmd-0.132/dmd/src/dmd/scope.h 2005-09-13 15:13:42.000000000 +0200
@@ -1,5 +1,5 @@
-// Copyright (c) 1999-2002 by Digital Mars
+// Copyright (c) 1999-2005 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
@@ -28,6 +28,7 @@
struct AggregateDeclaration;
struct AnonymousAggregateDeclaration;
struct FuncDeclaration;
+struct DocComment;
enum LINK;
enum PROT;
@@ -73,6 +74,10 @@
AnonymousAggregateDeclaration *anonAgg; // for temporary analysis
+ DocComment *lastdc; // documentation comment for last symbol at this scope
+ unsigned lastoffset; // offset in docbuf of where to insert next dec
+ OutBuffer *docbuf; // buffer for documentation output
+
static Scope *freelist;
static void *operator new(size_t sz);
static Scope *createGlobal(Module *module);
diff -uNr dmd-0.131/dmd/src/dmd/template.c dmd-0.132/dmd/src/dmd/template.c
--- dmd-0.131/dmd/src/dmd/template.c 2005-07-08 11:49:00.000000000 +0200
+++ dmd-0.132/dmd/src/dmd/template.c 2005-09-19 13:44:44.000000000 +0200
@@ -85,6 +85,7 @@
this->members = decldefs;
this->overnext = NULL;
this->scope = NULL;
+ this->onemember = NULL;
}
Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *)
@@ -155,6 +156,17 @@
paramscope->pop();
+ if (members && members->dim)
+ {
+ Dsymbol *s = (Dsymbol *)members->data[0];
+ s = s->oneMember();
+ if (s && s->ident && s->ident->equals(ident))
+ {
+ onemember = s;
+ s->parent = this;
+ }
+ }
+
/* BUG: should check:
* o no virtual functions or non-static data members of classes
*/
@@ -162,7 +174,9 @@
char *TemplateDeclaration::kind()
{
- return "template";
+ return (onemember && onemember->isAggregateDeclaration())
+ ? onemember->kind()
+ : (char *)"template";
}
/**********************************
@@ -402,7 +416,8 @@
{
int i;
- buf->writestring("template ");
+ buf->writestring(kind());
+ buf->writeByte(' ');
buf->writestring(ident->toChars());
buf->writeByte('(');
for (i = 0; i < parameters->dim; i++)
@@ -424,7 +439,7 @@
toCBuffer(&buf);
s = buf.toChars();
buf.data = NULL;
- return s + 9; // kludge to skip over 'template '
+ return s + strlen(kind()) + 1; // kludge to skip over 'template '
}
/* ======================== Type ============================================ */
diff -uNr dmd-0.131/dmd/src/dmd/template.h dmd-0.132/dmd/src/dmd/template.h
--- dmd-0.131/dmd/src/dmd/template.h 2005-04-04 17:00:58.000000000 +0200
+++ dmd-0.132/dmd/src/dmd/template.h 2005-09-19 11:29:18.000000000 +0200
@@ -1,5 +1,5 @@
-// Copyright (c) 1999-2004 by Digital Mars
+// Copyright (c) 1999-2005 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
@@ -37,6 +37,7 @@
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
Scope *scope;
+ Dsymbol *onemember; // if !=NULL then one member of this template
TemplateDeclaration(Loc loc, Identifier *id, Array *parameters, Array *decldefs);
Dsymbol *syntaxCopy(Dsymbol *);
@@ -46,6 +47,9 @@
char *kind();
char *toChars();
+ void emitComment(Scope *sc);
+// void toDocBuffer(OutBuffer *buf);
+
MATCH matchWithInstance(TemplateInstance *ti, Array *atypes, int flag);
int leastAsSpecialized(TemplateDeclaration *td2);
diff -uNr dmd-0.131/dmd/src/phobos/std/math.d dmd-0.132/dmd/src/phobos/std/math.d
--- dmd-0.131/dmd/src/phobos/std/math.d 2005-09-09 01:57:32.000000000 +0200
+++ dmd-0.132/dmd/src/phobos/std/math.d 2005-09-19 17:54:38.000000000 +0200
@@ -1,8 +1,20 @@
// math.d
+
+/**
+ * Boilerplate:
+ * $(std_boilerplate.html)
+ * Macros:
+ * WIKI = StdMath
+ */
+
/*
- * Copyright (C) 2001-2005 by Digital Mars, www.digitalmars.com
- * Written by Walter Bright
- *
+ * Author:
+ * Walter Bright
+ * Copyright:
+ * Copyright (c) 2001-2005 by Digital Mars,
+ * All Rights Reserved,
+ * www.digitalmars.com
+ * License:
* 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.
@@ -11,16 +23,22 @@
* 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 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.
+ *
+ *
Altered source versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ *
+ *
This notice may not be removed or altered from any source
+ * distribution.
+ *
+ */
+
+float sqrt(float x); /* intrinsic */
+double sqrt(double x); /* intrinsic */ /// ditto
+real sqrt(real x); /* intrinsic */ /// ditto
+
+creal sqrt(creal z)
+{
+ creal c;
+ real x,y,w,r;
+
+ if (z == 0)
+ {
+ c = 0;
+ }
+ else
+ { real z_re = z.re;
+ real z_im = z.im;
+
+ x = fabs(z_re);
+ y = fabs(z_im);
+ if (x >= y)
+ {
+ r = y / x;
+ w = sqrt(x) * sqrt(0.5 * (1 + sqrt(1 + r * r)));
+ }
+ else
+ {
+ r = x / y;
+ w = sqrt(y) * sqrt(0.5 * (r + sqrt(1 + r * r)));
+ }
+
+ if (z_re >= 0)
+ {
+ c = w + (z_im / (w + w)) * 1.0i;
+ }
+ else
+ {
+ if (z_im < 0)
+ w = -w;
+ c = z_im / (w + w) + w * 1.0i;
+ }
+ }
+ return c;
+}
+
+/***************************
+ * Cube root.
+ */
+
+real cbrt(real x) { return std.c.math.cbrtl(x); }
+
real exp(real x) { return std.c.math.expl(x); }
real exp2(real x) { return std.c.math.exp2l(x); }
+
+/******************************************
+ * Calculates the value of the natural logarithm base (e)
+ * raised to the power of x, minus 1.
+ *
+ * For very small x, expm1(x) is more accurate
+ * than exp(x)-1.
+ *
+ *
+ *
Special Values
+ *
x
ex-1
+ *
±0.0
±0.0
+ *
+∞
+∞
+ *
-∞
-1.0
+ *
+ */
+
real expm1(real x) { return std.c.math.expm1l(x); }
+
int ilogb(real x) { return std.c.math.ilogbl(x); }
+
+/**************************************
+ * Calculate the natural logarithm of x.
+ *
+ *
+ *
Special Values
+ *
+ *
x
log(x)
divide by 0?
invalid?
+ *
+ *
±0.0
-∞
yes
no
+ *
+ *
< 0.0
NAN
no
yes
+ *
+ *
+∞
+∞
no
no
+ *
+ */
+
real log(real x) { return std.c.math.logl(x); }
+
+/**************************************
+ * Calculate the base-10 logarithm of x.
+ *
+ *
+ *
Special Values
+ *
+ *
x
log10(x)
divide by 0?
invalid?
+ *
+ *
±0.0
-∞
yes
no
+ *
+ *
< 0.0
NAN
no
yes
+ *
+ *
+∞
+∞
no
no
+ *
+ */
+
real log10(real x) { return std.c.math.log10l(x); }
+
+/******************************************
+ * Calculates the natural logarithm of 1 + x.
+ *
+ * For very small x, log1p(x) will be more accurate than
+ * log(1 + x).
+ *
+ *
+ *
Special Values
+ *
+ *
x
log1p(x)
divide by 0?
invalid?
+ *
+ *
±0.0
±0.0
no
no
+ *
+ *
-1.0
-∞
yes
no
+ *
+ *
<-1.0
NAN
no
yes
+ *
+ *
+∞
-∞
no
no
+ *
+ */
+
real log1p(real x) { return std.c.math.log1pl(x); }
+
real log2(real x) { return std.c.math.log2l(x); }
real logb(real x) { return std.c.math.logbl(x); }
real modf(real x, inout real y) { return std.c.math.modfl(x,&y); }
-real cbrt(real x) { return std.c.math.cbrtl(x); }
real erf(real x) { return std.c.math.erfl(x); }
real erfc(real x) { return std.c.math.erfcl(x); }
real ceil(real x) { return std.c.math.ceill(x); }
real floor(real x) { return std.c.math.floorl(x); }
-const real PI = 0x1.921fb54442d1846ap+1; // 3.14159 fldpi
-const real LOG2T = 0x1.a934f0979a3715fcp+1; // 3.32193 fldl2t
-const real LOG2E = 0x1.71547652b82fe178p+0; // 1.4427 fldl2e
-const real LOG2 = 0x1.34413509f79fef32p-2; // 0.30103 fldlg2
-const real LN2 = 0x1.62e42fefa39ef358p-1; // 0.693147 fldln2
-const real E = 2.7182818284590452354L;
-const real LOG10E = 0.43429448190325182765;
-const real LN10 = 2.30258509299404568402;
-const real PI_2 = 1.57079632679489661923;
-const real PI_4 = 0.78539816339744830962;
-const real M_1_PI = 0.31830988618379067154;
-const real M_2_PI = 0.63661977236758134308;
-const real M_2_SQRTPI = 1.12837916709551257390;
-const real SQRT2 = 1.41421356237309504880;
-const real SQRT1_2 = 0.70710678118654752440;
-
-/*
- Octal versions:
- PI/64800 0.00001 45530 36176 77347 02143 15351 61441 26767
- PI/180 0.01073 72152 11224 72344 25603 54276 63351 22056
- PI/8 0.31103 75524 21026 43021 51423 06305 05600 67016
- SQRT(1/PI) 0.44067 27240 41233 33210 65616 51051 77327 77303
- 2/PI 0.50574 60333 44710 40522 47741 16537 21752 32335
- PI/4 0.62207 73250 42055 06043 23046 14612 13401 56034
- SQRT(2/PI) 0.63041 05147 52066 24106 41762 63612 00272 56161
-
- PI 3.11037 55242 10264 30215 14230 63050 56006 70163
- LOG2 0.23210 11520 47674 77674 61076 11263 26013 37111
- */
-
-
/*********************************
* Is number a nan?
*/
@@ -145,7 +431,9 @@
/*********************************
* Is number normalized?
- * Need one for each format because subnormal floats might
+ */
+
+/* Need one for each format because subnormal floats might
* be converted to normal reals.
*/
@@ -159,6 +447,8 @@
return e && e != 0x7F800000;
}
+/// ditto
+
int isnormal(double d)
{
uint *p = cast(uint *)&d;
@@ -168,6 +458,8 @@
return e && e != 0x7FF00000;
}
+/// ditto
+
int isnormal(real e)
{
ushort* pe = cast(ushort *)&e;
@@ -190,7 +482,9 @@
/*********************************
* Is number subnormal? (Also called "denormal".)
* Subnormals have a 0 exponent and a 0 most significant mantissa bit.
- * Need one for each format because subnormal floats might
+ */
+
+/* Need one for each format because subnormal floats might
* be converted to normal reals.
*/
@@ -210,6 +504,8 @@
assert(f != 0);
}
+/// ditto
+
int issubnormal(double d)
{
uint *p = cast(uint *)&d;
@@ -225,6 +521,8 @@
assert(f != 0);
}
+/// ditto
+
int issubnormal(real e)
{
ushort* pe = cast(ushort *)&e;
@@ -322,129 +620,57 @@
assert(isnan(e) && signbit(e));
}
-/****************************************************************************
- * Tangent.
- */
-
-real tan(real x)
-{
- asm
- {
- fld x[EBP] ; // load theta
- fxam ; // test for oddball values
- fstsw AX ;
- sahf ;
- jc trigerr ; // x is NAN, infinity, or empty
- // 387's can handle denormals
-SC18: fptan ;
- fstp ST(0) ; // dump X, which is always 1
- fstsw AX ;
- sahf ;
- jnp Lret ; // C2 = 1 (x is out of range)
-
- // Do argument reduction to bring x into range
- fldpi ;
- fxch ;
-SC17: fprem1 ;
- fstsw AX ;
- sahf ;
- jp SC17 ;
- fstp ST(1) ; // remove pi from stack
- jmp SC18 ;
-
-trigerr:
- fstp ST(0) ; // dump theta
- }
- return real.nan;
-
-Lret:
- ;
-}
-
-unittest
-{
- static real vals[][2] = // angle,tan
- [
- [ 0, 0],
- [ .5, .5463024898],
- [ 1, 1.557407725],
- [ 1.5, 14.10141995],
- [ 2, -2.185039863],
- [ 2.5,-.7470222972],
- [ 3, -.1425465431],
- [ 3.5, .3745856402],
- [ 4, 1.157821282],
- [ 4.5, 4.637332055],
- [ 5, -3.380515006],
- [ 5.5,-.9955840522],
- [ 6, -.2910061914],
- [ 6.5, .2202772003],
- [ 10, .6483608275],
-
- // special angles
- [ PI_4, 1],
- //[ PI_2, real.infinity],
- [ 3*PI_4, -1],
- [ PI, 0],
- [ 5*PI_4, 1],
- //[ 3*PI_2, -real.infinity],
- [ 7*PI_4, -1],
- [ 2*PI, 0],
-
- // overflow
- [ real.infinity, real.nan],
- [ real.nan, real.nan],
- [ 1e+100, real.nan],
- ];
- int i;
-
- for (i = 0; i < vals.length; i++)
- {
- real x = vals[i][0];
- real r = vals[i][1];
- real t = tan(x);
-
- //printf("tan(%Lg) = %Lg, should be %Lg\n", x, t, r);
- assert(mfeq(r, t, .0000001));
-
- x = -x;
- r = -r;
- t = tan(x);
- //printf("tan(%Lg) = %Lg, should be %Lg\n", x, t, r);
- assert(mfeq(r, t, .0000001));
- }
-}
-
-
-/****************************************************************************
- * hypotenuese.
- * This is based on code from:
- * Cephes Math Library Release 2.1: January, 1989
- * Copyright 1984, 1987, 1989 by Stephen L. Moshier
- * Direct inquiries to 30 Frost Street, Cambridge, MA 02140
+/***********************************************************************
+ * Calculates the length of the
+ * hypotenuse of a right-angled triangle with sides of length x and y.
+ * The hypotenuse is the value of the square root of
+ * the sums of the squares of x and y:
+ *
+ * sqrt(x² + y²)
+ *
+ * Note that hypot(x, y), hypot(y, x) and
+ * hypot(x, -y) are equivalent.
+ *
+ *
+ *
Special Values
+ *
+ *
x
y
hypot(x, y)
invalid?
+ *
+ *
x
±0.0
|x|
no
+ *
+ *
±∞
y
+∞
no
+ *
+ *
±∞
NAN
+∞
no
+ *
*/
-real hypot(real zre, real zim)
+real hypot(real x, real y)
{
+ /*
+ * This is based on code from:
+ * Cephes Math Library Release 2.1: January, 1989
+ * Copyright 1984, 1987, 1989 by Stephen L. Moshier
+ * Direct inquiries to 30 Frost Street, Cambridge, MA 02140
+ */
const int PRECL = 32;
const int MAXEXPL = real.max_exp; //16384;
const int MINEXPL = real.min_exp; //-16384;
- real x, y, b, re, im;
+ real xx, yy, b, re, im;
int ex, ey, e;
// Note, hypot(INFINITY,NAN) = INFINITY.
- if (isinf(zre) || isinf(zim))
+ if (isinf(x) || isinf(y))
return real.infinity;
- if (isnan(zre))
- return zre;
- if (isnan(zim))
- return zim;
+ if (isnan(x))
+ return x;
+ if (isnan(y))
+ return y;
- re = fabs(zre);
- im = fabs(zim);
+ re = fabs(x);
+ im = fabs(y);
if (re == 0.0)
return im;
@@ -452,8 +678,8 @@
return re;
// Get the exponents of the numbers
- x = frexp(re, ex);
- y = frexp(im, ey);
+ xx = frexp(re, ex);
+ yy = frexp(im, ey);
// Check if one number is tiny compared to the other
e = ex - ey;
@@ -466,14 +692,14 @@
e = (ex + ey) >> 1;
// Rescale so mean is about 1
- x = ldexp(re, -e);
- y = ldexp(im, -e);
+ xx = ldexp(re, -e);
+ yy = ldexp(im, -e);
// Hypotenuse of the right triangle
- b = sqrt(x * x + y * y);
+ b = sqrt(xx * xx + yy * yy);
// Compute the exponent of the answer.
- y = frexp(b, ey);
+ yy = frexp(b, ey);
ey = e + ey;
// Check it for overflow and underflow.
@@ -520,55 +746,65 @@
}
/*********************************************************************
+ * Separate floating point value into significand and exponent.
+ *
* Returns:
- * x such that value=x*2**n, .5 <= |x| < 1.0
- * x has same sign as value.
- * *eptr = n
+ *
Calculate and return x and exp such that
+ * value =x*2exp and
+ * .5 <= |x| < 1.0
+ * x has same sign as value.
*
- * Special cases:
- * value x *eptr
- * +-0.0 +-0.0 0
- * +-inf +-inf int.max/int.min
- * +-NaN +-NaN int.min
- * +-NaNs +-NaN int.min
+ *
+ *
Special values
+ *
+ *
value
returns
exp
+ *
+ *
±0.0
±0.0
0
+ *
+ *
+∞
+∞
int.max
+ *
+ *
-∞
-∞
int.min
+ *
+ *
±NAN
±NAN
int.min
+ *
*/
-real frexp(real value, out int eptr)
+real frexp(real value, out int exp)
{
ushort* vu = cast(ushort*)&value;
long* vl = cast(long*)&value;
- uint exp;
+ uint ex;
// If exponent is non-zero
- exp = vu[4] & 0x7FFF;
- if (exp)
+ ex = vu[4] & 0x7FFF;
+ if (ex)
{
- if (exp == 0x7FFF)
+ if (ex == 0x7FFF)
{ // infinity or NaN
if (*vl & 0x7FFFFFFFFFFFFFFF) // if NaN
{ *vl |= 0xC000000000000000; // convert NANS to NANQ
- eptr = int.min;
+ exp = int.min;
}
else if (vu[4] & 0x8000)
{ // negative infinity
- eptr = int.min;
+ exp = int.min;
}
else
{ // positive infinity
- eptr = int.max;
+ exp = int.max;
}
}
else
{
- eptr = exp - 0x3FFE;
+ exp = ex - 0x3FFE;
vu[4] = (0x8000 & vu[4]) | 0x3FFE;
}
}
else if (!*vl)
{
// value is +-0.0
- eptr = 0;
+ exp = 0;
}
else
{ // denormal
@@ -579,7 +815,7 @@
i--;
*vl <<= 1;
} while (*vl > 0);
- eptr = i;
+ exp = i;
vu[4] = (0x8000 & vu[4]) | 0x3FFE;
}
return value;
@@ -588,7 +824,7 @@
unittest
{
- static real vals[][3] = // x,frexp,eptr
+ static real vals[][3] = // x,frexp,exp
[
[0.0, 0.0, 0],
[-0.0, -0.0, 0],
@@ -663,6 +899,8 @@
return p;
}
+/// ditto
+
real pow(real x, int n)
{
if (n < 0)
@@ -777,49 +1015,6 @@
assert(pow(x,8) == (x * x) * (x * x) * (x * x) * (x * x));
}
-/*****************************************
- */
-
-creal sqrt(creal z)
-{
- creal c;
- real x,y,w,r;
-
- if (z == 0)
- {
- c = 0;
- }
- else
- { real z_re = z.re;
- real z_im = z.im;
-
- x = fabs(z_re);
- y = fabs(z_im);
- if (x >= y)
- {
- r = y / x;
- w = sqrt(x) * sqrt(0.5 * (1 + sqrt(1 + r * r)));
- }
- else
- {
- r = x / y;
- w = sqrt(y) * sqrt(0.5 * (r + sqrt(1 + r * r)));
- }
-
- if (z_re >= 0)
- {
- c = w + (z_im / (w + w)) * 1.0i;
- }
- else
- {
- if (z_im < 0)
- w = -w;
- c = z_im / (w + w) + w * 1.0i;
- }
- }
- return c;
-}
-
/****************************************
* Simple function to compare two floating point values
* to a specified precision.
@@ -846,33 +1041,46 @@
/**************************************
- int feqrel(real x, real y)
- To what precision is x equal to y?
- Public Domain. Author: Don Clugston, 18 Aug 2005.
-
- Returns the number of mantissa bits which are equal in x and y.
- eg, 0x1.F8p+60 and 0x1.F1p+60 are equal to 5 bits of precision.
- If x == y, then feqrel(x, y) == real.mant_dig.
-
- If x and y differ by a factor of two or more, or if one or both
- is a nan, the return value is 0.
-*/
+ * To what precision is x equal to y?
+ *
+ * Returns: the number of mantissa bits which are equal in x and y.
+ * eg, 0x1.F8p+60 and 0x1.F1p+60 are equal to 5 bits of precision.
+ *
+ *
+ *
Special values
+ *
+ *
x
y
feqrel(x, y)
+ *
+ *
x
x
real.mant_dig
+ *
+ *
x
>= 2*x
0
+ *
+ *
x
<= x/2
0
+ *
+ *
NAN
any
0
+ *
+ *
any
NAN
0
+ *
+ */
-int feqrel(real a, real b)
+int feqrel(real x, real y)
{
- if (a == b)
+ /* Public Domain. Author: Don Clugston, 18 Aug 2005.
+ */
+
+ if (x == y)
return real.mant_dig; // ensure diff!=0, cope with INF.
- real diff = fabs(a-b);
+ real diff = fabs(x - y);
- ushort *pa = cast(ushort *)(&a);
- ushort *pb = cast(ushort *)(&b);
+ ushort *pa = cast(ushort *)(&x);
+ ushort *pb = cast(ushort *)(&y);
ushort *pd = cast(ushort *)(&diff);
- // The difference in abs(exponent) between a or b and abs(a-b)
- // is equal to the number of mantissa bits of a which are
- // equal to b. If negative, a and b have different exponents.
- // If positive, a and b are equal to 'bitsdiff' bits.
+ // The difference in abs(exponent) between x or y and abs(x-y)
+ // is equal to the number of mantissa bits of x which are
+ // equal to y. If negative, x and y have different exponents.
+ // If positive, x and y are equal to 'bitsdiff' bits.
// AND with 0x7FFF to form the absolute value.
// To avoid out-by-1 errors, we subtract 1 so it rounds down
// if the exponents were different. This means 'bitsdiff' is
diff -uNr dmd-0.131/dmd/src/phobos/std/outbuffer.d dmd-0.132/dmd/src/phobos/std/outbuffer.d
--- dmd-0.131/dmd/src/phobos/std/outbuffer.d 2005-09-09 01:57:34.000000000 +0200
+++ dmd-0.132/dmd/src/phobos/std/outbuffer.d 2005-09-19 17:54:38.000000000 +0200
@@ -1,16 +1,18 @@
// outbuffer.d
+
+/**
+ * Boilerplate:
+ * $(std_boilerplate.html)
+ * Macros:
+ * WIKI = StdOutbuffer
+ * Copyright:
+ * Copyright (c) 2001-2005 by Digital Mars
+ * All Rights Reserved
+ * www.digitalmars.com
+ */
+
+
// Written by Walter Bright
-// Copyright (c) 2001 Digital Mars
-// All Rights Reserved
-// www.digitalmars.com
-
-// OutBuffer provides a way to build up an array of bytes out
-// of raw data. It is useful for things like preparing an
-// array of bytes to write out to a file.
-// OutBuffer's byte order is the format native to the computer.
-// To control the byte order (endianness), use a class derived
-// from OutBuffer.
-// To convert an array of bytes back into raw data, use InBuffer.
module std.outbuffer;
@@ -22,6 +24,15 @@
import std.c.stdarg;
}
+/*********************************************
+ * OutBuffer provides a way to build up an array of bytes out
+ * of raw data. It is useful for things like preparing an
+ * array of bytes to write out to a file.
+ * OutBuffer's byte order is the format native to the computer.
+ * To control the byte order (endianness), use a class derived
+ * from OutBuffer.
+ */
+
class OutBuffer
{
ubyte data[];
@@ -44,6 +55,15 @@
ubyte[] toBytes() { return data[0 .. offset]; }
+ /***********************************
+ * Preallocate nbytes more to the size of the internal buffer.
+ *
+ * This is a
+ * speed optimization, a good guess at the maximum size of the resulting
+ * buffer will improve performance by eliminating reallocations and copying.
+ */
+
+
void reserve(uint nbytes)
in
{
@@ -62,6 +82,10 @@
}
}
+ /*************************************
+ * Append data to the internal buffer.
+ */
+
void write(ubyte[] bytes)
{
reserve(bytes.length);
@@ -69,81 +93,85 @@
offset += bytes.length;
}
- void write(ubyte b)
+ void write(ubyte b) /// ditto
{
reserve(ubyte.sizeof);
this.data[offset] = b;
offset += ubyte.sizeof;
}
- void write(byte b) { write(cast(ubyte)b); }
- void write(char c) { write(cast(ubyte)c); }
+ void write(byte b) { write(cast(ubyte)b); } /// ditto
+ void write(char c) { write(cast(ubyte)c); } /// ditto
- void write(ushort w)
+ void write(ushort w) /// ditto
{
reserve(ushort.sizeof);
*cast(ushort *)&data[offset] = w;
offset += ushort.sizeof;
}
- void write(short s) { write(cast(ushort)s); }
+ void write(short s) { write(cast(ushort)s); } /// ditto
- void write(wchar c)
+ void write(wchar c) /// ditto
{
reserve(wchar.sizeof);
*cast(wchar *)&data[offset] = c;
offset += wchar.sizeof;
}
- void write(uint w)
+ void write(uint w) /// ditto
{
reserve(uint.sizeof);
*cast(uint *)&data[offset] = w;
offset += uint.sizeof;
}
- void write(int i) { write(cast(uint)i); }
+ void write(int i) { write(cast(uint)i); } /// ditto
- void write(ulong l)
+ void write(ulong l) /// ditto
{
reserve(ulong.sizeof);
*cast(ulong *)&data[offset] = l;
offset += ulong.sizeof;
}
- void write(long l) { write(cast(ulong)l); }
+ void write(long l) { write(cast(ulong)l); } /// ditto
- void write(float f)
+ void write(float f) /// ditto
{
reserve(float.sizeof);
*cast(float *)&data[offset] = f;
offset += float.sizeof;
}
- void write(double f)
+ void write(double f) /// ditto
{
reserve(double.sizeof);
*cast(double *)&data[offset] = f;
offset += double.sizeof;
}
- void write(real f)
+ void write(real f) /// ditto
{
reserve(real.sizeof);
*cast(real *)&data[offset] = f;
offset += real.sizeof;
}
- void write(char[] s)
+ void write(char[] s) /// ditto
{
write(cast(ubyte[])s);
}
- void write(OutBuffer buf)
+ void write(OutBuffer buf) /// ditto
{
write(buf.toBytes());
}
+ /****************************************
+ * Append nbytes of 0 to the internal buffer.
+ */
+
void fill0(uint nbytes)
{
reserve(nbytes);
@@ -194,6 +222,10 @@
}
}
+ /**************************************
+ * Convert internal buffer to array of chars.
+ */
+
char[] toString()
{
//printf("OutBuffer.toString()\n");
@@ -201,7 +233,7 @@
}
/*****************************************
- * vprintf() into buffer.
+ * Append output of C's vprintf() to internal buffer.
*/
void vprintf(char[] format, va_list args)
@@ -253,7 +285,7 @@
}
/*****************************************
- * printf() into buffer.
+ * Append output of C's printf() to internal buffer.
*/
void printf(char[] format, ...)
@@ -265,6 +297,8 @@
}
/*****************************************
+ * At offset index into buffer, create nbytes of space by shifting upwards
+ * all data past index.
*/
void spread(uint index, uint nbytes)
diff -uNr dmd-0.131/dmd/src/phobos/std/path.d dmd-0.132/dmd/src/phobos/std/path.d
--- dmd-0.131/dmd/src/phobos/std/path.d 2005-09-09 01:57:32.000000000 +0200
+++ dmd-0.132/dmd/src/phobos/std/path.d 2005-09-19 17:54:38.000000000 +0200
@@ -1,7 +1,14 @@
-// Copyright (c) 2001-2003 by Digital Mars
-// All Rights Reserved
-// www.digitalmars.com
+/**
+ * Boilerplate:
+ * $(std_boilerplate.html)
+ * Macros:
+ * WIKI = StdPath
+ * Copyright:
+ * Copyright (c) 2001-2005 by Digital Mars
+ * All Rights Reserved
+ * www.digitalmars.com
+ */
// File name parsing
@@ -13,21 +20,22 @@
version(Win32)
{
- const char[1] sep = "\\";
- const char[1] altsep = "/";
- const char[1] pathsep = ";";
- const char[2] linesep = "\r\n";
- const char[1] curdir = ".";
- const char[2] pardir = "..";
+
+ const char[1] sep = "\\"; /// String used to separate directory names in a path.
+ const char[1] altsep = "/"; /// Alternate version of sep[], used in Windows.
+ const char[1] pathsep = ";"; /// Path separator string.
+ const char[2] linesep = "\r\n"; /// String used to separate lines.
+ const char[1] curdir = "."; /// String representing the current directory.
+ const char[2] pardir = ".."; /// String representing the parent directory.
}
version(linux)
{
- const char[1] sep = "/";
- const char[0] altsep;
- const char[1] pathsep = ":";
- const char[1] linesep = "\n";
- const char[1] curdir = ".";
- const char[2] pardir = "..";
+ const char[1] sep = "/"; /// String used to separate directory names in a path.
+ const char[0] altsep; /// Alternate version of sep[], used in Windows.
+ const char[1] pathsep = ":"; /// Path separator string.
+ const char[1] linesep = "\n"; /// String used to separate lines.
+ const char[1] curdir = "."; /// String representing the current directory.
+ const char[2] pardir = ".."; /// String representing the parent directory.
}
/**************************
@@ -219,54 +227,55 @@
}
/****************************
- * Put a default extension on fullname if it doesn't already
- * have an extension.
+ * If filename doesn't already have an extension,
+ * append the extension ext and return the result.
*/
-char[] defaultExt(char[] fullname, char[] ext)
+char[] defaultExt(char[] filename, char[] ext)
{
char[] existing;
- existing = getExt(fullname);
+ existing = getExt(filename);
if (existing.length == 0)
{
- // Check for fullname ending in '.'
- if (fullname.length && fullname[fullname.length - 1] == '.')
- fullname ~= ext;
+ // Check for filename ending in '.'
+ if (filename.length && filename[filename.length - 1] == '.')
+ filename ~= ext;
else
- fullname = fullname ~ "." ~ ext;
+ filename = filename ~ "." ~ ext;
}
- return fullname;
+ return filename;
}
/****************************
- * Strip the old extension off and add the new one.
+ * Strip any existing extension off of filename and add the new extension ext.
+ * Return the result.
*/
-char[] addExt(char[] fullname, char[] ext)
+char[] addExt(char[] filename, char[] ext)
{
char[] existing;
- existing = getExt(fullname);
+ existing = getExt(filename);
if (existing.length == 0)
{
- // Check for fullname ending in '.'
- if (fullname.length && fullname[fullname.length - 1] == '.')
- fullname ~= ext;
+ // Check for filename ending in '.'
+ if (filename.length && filename[filename.length - 1] == '.')
+ filename ~= ext;
else
- fullname = fullname ~ "." ~ ext;
+ filename = filename ~ "." ~ ext;
}
else
{
- fullname = fullname[0 .. fullname.length - existing.length] ~ ext;
+ filename = filename[0 .. filename.length - existing.length] ~ ext;
}
- return fullname;
+ return filename;
}
/*************************************
- * Determine if absolute path name.
+ * Return !=0 if path is absolute (i.e. it starts from the root directory).
*/
int isabs(char[] path)
@@ -277,7 +286,7 @@
}
/*************************************
- * Join two path components.
+ * Join two path components p1 and p2 and return the result.
*/
char[] join(char[] p1, char[] p2)
@@ -422,7 +431,7 @@
/*********************************
- * Match file name characters.
+ * Match file name characters c1 and c2.
* Case sensitivity depends on the operating system.
*/
@@ -447,20 +456,22 @@
}
/************************************
- * Match filename strings with pattern[], using the following wildcards:
- * * match 0 or more characters
- * ? match any character
- * [chars] match any character that appears between the []
- * [!chars] match any character that does not appear between the [! ]
+ * Match filename with pattern, using the following wildcards:
+ *
+ *
+ *
*
match 0 or more characters
+ *
?
match any character
+ *
[chars]
match any character that appears between the []
+ *
[!chars]
match any character that does not appear between the [! ]
+ *
*
* Matching is case sensitive on a file system that is case sensitive.
*
* Returns:
- * true match
- * false no match
+ * !=0 for match
*/
-int fnmatch(char[] name, char[] pattern)
+int fnmatch(char[] filename, char[] pattern)
in
{
// Verify that pattern[] is valid
@@ -505,23 +516,23 @@
case '*':
if (pi + 1 == pattern.length)
goto match;
- for (j = ni; j < name.length; j++)
+ for (j = ni; j < filename.length; j++)
{
- if (fnmatch(name[j .. name.length], pattern[pi + 1 .. pattern.length]))
+ if (fnmatch(filename[j .. filename.length], pattern[pi + 1 .. pattern.length]))
goto match;
}
goto nomatch;
case '?':
- if (ni == name.length)
+ if (ni == filename.length)
goto nomatch;
ni++;
break;
case '[':
- if (ni == name.length)
+ if (ni == filename.length)
goto nomatch;
- nc = name[ni];
+ nc = filename[ni];
ni++;
not = 0;
pi++;
@@ -544,16 +555,16 @@
break;
default:
- if (ni == name.length)
+ if (ni == filename.length)
goto nomatch;
- nc = name[ni];
+ nc = filename[ni];
if (!fncharmatch(pc, nc))
goto nomatch;
ni++;
break;
}
}
- if (ni < name.length)
+ if (ni < filename.length)
goto nomatch;
match:
diff -uNr dmd-0.131/dmd/src/phobos/std/stream.d dmd-0.132/dmd/src/phobos/std/stream.d
--- dmd-0.131/dmd/src/phobos/std/stream.d 2005-09-09 01:57:34.000000000 +0200
+++ dmd-0.132/dmd/src/phobos/std/stream.d 2005-09-19 17:54:38.000000000 +0200
@@ -1,3 +1,10 @@
+/**
+ * Boilerplate:
+ * $(std_boilerplate.html)
+ * Macros:
+ * WIKI = StdStream
+ */
+
/*
* Copyright (c) 2001-2005
* Pavel "EvilOne" Minayev
@@ -31,24 +38,27 @@
* TArrayStream a stream wrapping an array-like buffer
*/
-// generic Stream exception, base class for all
-// other Stream exceptions
+/// A base class for stream exceptions.
class StreamException: Exception {
+ /// Construct a StreamException with given error message.
this(char[] msg) { super(msg); }
}
-// thrown when unable to read data from Stream
+/// Thrown when unable to read data from Stream.
class ReadException: StreamException {
+ /// Construct a ReadException with given error message.
this(char[] msg) { super(msg); }
}
-// thrown when unable to write data to Stream
+/// Thrown when unable to write data to Stream.
class WriteException: StreamException {
+ /// Construct a WriteException with given error message.
this(char[] msg) { super(msg); }
}
-// thrown when unable to move Stream pointer
+/// Thrown when unable to move Stream pointer.
class SeekException: StreamException {
+ /// Construct a SeekException with given error message.
this(char[] msg) { super(msg); }
}
@@ -70,198 +80,326 @@
private import std.file;
}
-// Interface for readable streams
+/// InputStream is the interface for readable streams.
+
interface InputStream {
- // reads block of data of specified size,
- // throws ReadException on error
+
+ /***
+ * Read exactly size bytes into the buffer.
+ *
+ * Throws a ReadException if it is not correct.
+ */
void readExact(void* buffer, size_t size);
- // reads block of data big enough to fill the given
- // array, returns actual number of bytes read
+ /***
+ * Read a block of data big enough to fill the given array buffer.
+ *
+ * Returns: the actual number of bytes read. Unfilled bytes are not modified.
+ */
size_t read(ubyte[] buffer);
- // read a single value of desired type,
- // throw ReadException on error
+ /***
+ * Read a basic type or counted string.
+ *
+ * Throw a ReadException if it could not be read.
+ * Outside of byte, ubyte, and char, the format is
+ * implementation-specific and should not be used except as opposite actions
+ * to write.
+ */
void read(out byte x);
- void read(out ubyte x);
- void read(out short x);
- void read(out ushort x);
- void read(out int x);
- void read(out uint x);
- void read(out long x);
- void read(out ulong x);
- void read(out float x);
- void read(out double x);
- void read(out real x);
- void read(out ifloat x);
- void read(out idouble x);
- void read(out ireal x);
- void read(out cfloat x);
- void read(out cdouble x);
- void read(out creal x);
- void read(out char x);
- void read(out wchar x);
- void read(out dchar x);
+ void read(out ubyte x); /// ditto
+ void read(out short x); /// ditto
+ void read(out ushort x); /// ditto
+ void read(out int x); /// ditto
+ void read(out uint x); /// ditto
+ void read(out long x); /// ditto
+ void read(out ulong x); /// ditto
+ void read(out float x); /// ditto
+ void read(out double x); /// ditto
+ void read(out real x); /// ditto
+ void read(out ifloat x); /// ditto
+ void read(out idouble x); /// ditto
+ void read(out ireal x); /// ditto
+ void read(out cfloat x); /// ditto
+ void read(out cdouble x); /// ditto
+ void read(out creal x); /// ditto
+ void read(out char x); /// ditto
+ void read(out wchar x); /// ditto
+ void read(out dchar x); /// ditto
// reads a string, written earlier by write()
- void read(out char[] s);
+ void read(out char[] s); /// ditto
// reads a Unicode string, written earlier by write()
- void read(out wchar[] s);
+ void read(out wchar[] s); /// ditto
- // reads a line, terminated by either CR, LF, CR/LF, or EOF
+ /***
+ * Read a line that is terminated with some combination of carriage return and
+ * line feed or end-of-file.
+ *
+ * The terminators are not included. The wchar version
+ * is identical. The optional buffer parameter is filled (reallocating
+ * it if necessary) and a slice of the result is returned.
+ */
char[] readLine();
-
- // reads a line, terminated by either CR, LF, CR/LF, or EOF
- // reusing the memory in result and reallocating if needed
- char[] readLine(char[] result);
-
- // reads a Unicode line, terminated by either CR, LF, CR/LF,
- // or EOF; pretty much the same as the above, working with
- // wchars rather than chars
- wchar[] readLineW();
-
- // reads a Unicode line, terminated by either CR, LF, CR/LF,
- // or EOF; pretty much the same as the above, working with
- // wchars rather than chars
- wchar[] readLineW(wchar[] result);
+ char[] readLine(char[] result); /// ditto
+ wchar[] readLineW(); /// ditto
+ wchar[] readLineW(wchar[] result); /// ditto
+
+ /***
+ * Overload foreach statements to read the stream line by line and call the
+ * supplied delegate with each line or with each line with line number.
+ *
+ * The string passed in line may be reused between calls to the delegate.
+ * Line numbering starts at 1.
+ * Breaking out of the foreach will leave the stream
+ * position at the beginning of the next line to be read.
+ * For example, to echo a file line-by-line with line numbers run:
+ * ------------------------------------
+ * Stream file = new BufferedFile("sample.txt");
+ * foreach(ulong n, char[] line; file) {
+ * stdout.writefln("line %d: %s",n,line);
+ * }
+ * file.close();
+ * ------------------------------------
+ */
// iterate through the stream line-by-line
int opApply(int delegate(inout char[] line) dg);
- int opApply(int delegate(inout ulong n, inout char[] line) dg);
- int opApply(int delegate(inout wchar[] line) dg);
- int opApply(int delegate(inout ulong n, inout wchar[] line) dg);
+ int opApply(int delegate(inout ulong n, inout char[] line) dg); /// ditto
+ int opApply(int delegate(inout wchar[] line) dg); /// ditto
+ int opApply(int delegate(inout ulong n, inout wchar[] line) dg); /// ditto
- // reads a string of given length, throws
- // ReadException on error
+ /// Read a string of the given length,
+ /// throwing ReadException if there was a problem.
char[] readString(size_t length);
- // reads a Unicode string of given length, throws
- // ReadException on error
+ /***
+ * Read a string of the given length, throwing ReadException if there was a
+ * problem.
+ *
+ * The file format is implementation-specific and should not be used
+ * except as opposite actions to write.
+ */
+
wchar[] readStringW(size_t length);
- // reads and returns next character from the stream,
- // handles characters pushed back by ungetc()
- // return char.init on EOF
- char getc();
- // reads and returns next Unicode character from the
- // stream, handles characters pushed back by ungetc()
- // return wchar.init on EOF
- wchar getcw();
+ /***
+ * Read and return the next character in the stream.
+ *
+ * This is the only method that will handle ungetc properly.
+ * getcw's format is implementation-specific.
+ * If EOF is reached then getc returns char.init and getcw returns wchar.init.
+ */
- // pushes back character c into the stream; only has
- // effect on further calls to getc() and getcw()
- char ungetc(char c);
+ char getc();
+ wchar getcw(); /// ditto
- // pushes back Unicode character c into the stream; only
- // has effect on further calls to getc() and getcw()
- wchar ungetcw(wchar c);
+ /***
+ * Push a character back onto the stream.
+ *
+ * They will be returned in first-in last-out order from getc/getcw.
+ * Only has effect on further calls to getc() and getcw().
+ */
+ char ungetc(char c);
+ wchar ungetcw(wchar c); /// ditto
+ /***
+ * Scan a string from the input using a similar form to C's scanf
+ * and std.format.
+ *
+ * An argument of type char[] is interpreted as a format string.
+ * All other arguments must be pointer types.
+ * If a format string is not present a default will be supplied computed from
+ * the base type of the pointer type. An argument of type char[]* is filled
+ * (possibly with appending characters) and a slice of the result is assigned
+ * back into the argument. For example the following readf statements
+ * are equivalent:
+ * --------------------------
+ * int x;
+ * double y;
+ * char[] s;
+ * file.readf(&x, " hello ", &y, &s);
+ * file.readf("%d hello %f %s", &x, &y, &s);
+ * file.readf("%d hello %f", &x, &y, "%s", &s);
+ * --------------------------
+ */
int vreadf(TypeInfo[] arguments, void* args);
+ int readf(...); /// ditto
- int readf(...);
-
+ /// Retrieve the number of bytes available for immediate reading.
size_t available();
+
+ /***
+ * Return whether the current file position is the same as the end of the
+ * file.
+ *
+ * This does not require actually reading past the end, as with stdio. For
+ * non-seekable streams this might only return true after attempting to read
+ * past the end.
+ */
+
bool eof();
- bool isOpen();
+
+ bool isOpen(); /// Return true if the stream is currently open.
}
-// Interface for writable streams
+/// Interface for writable streams.
interface OutputStream {
- // writes block of data of specified size,
- // throws WriteException on error
+
+ /***
+ * Write exactly size bytes from buffer, or throw a WriteException if that
+ * could not be done.
+ */
void writeExact(void* buffer, size_t size);
- // writes the given array of bytes, returns
- // actual number of bytes written
+ /***
+ * Write as much of the buffer as possible,
+ * returning the number of bytes written.
+ */
size_t write(ubyte[] buffer);
- // write a single value of desired type,
- // throw WriteException on error
+ /***
+ * Write a basic type.
+ *
+ * Outside of byte, ubyte, and char, the format is implementation-specific
+ * and should only be used in conjunction with read.
+ * Throw WriteException on error.
+ */
void write(byte x);
- void write(ubyte x);
- void write(short x);
- void write(ushort x);
- void write(int x);
- void write(uint x);
- void write(long x);
- void write(ulong x);
- void write(float x);
- void write(double x);
- void write(real x);
- void write(ifloat x);
- void write(idouble x);
- void write(ireal x);
- void write(cfloat x);
- void write(cdouble x);
- void write(creal x);
- void write(char x);
- void write(wchar x);
- void write(dchar x);
+ void write(ubyte x); /// ditto
+ void write(short x); /// ditto
+ void write(ushort x); /// ditto
+ void write(int x); /// ditto
+ void write(uint x); /// ditto
+ void write(long x); /// ditto
+ void write(ulong x); /// ditto
+ void write(float x); /// ditto
+ void write(double x); /// ditto
+ void write(real x); /// ditto
+ void write(ifloat x); /// ditto
+ void write(idouble x); /// ditto
+ void write(ireal x); /// ditto
+ void write(cfloat x); /// ditto
+ void write(cdouble x); /// ditto
+ void write(creal x); /// ditto
+ void write(char x); /// ditto
+ void write(wchar x); /// ditto
+ void write(dchar x); /// ditto
- // writes a string, together with its length
+ /***
+ * Writes a string, together with its length.
+ *
+ * The format is implementation-specific
+ * and should only be used in conjunction with read.
+ * Throw WriteException on error.
+ */
void write(char[] s);
+ void write(wchar[] s); /// ditto
- // writes a Unicode string, together with its length
- void write(wchar[] s);
-
- // writes a line, throws WriteException on error
+ /***
+ * Write a line of text,
+ * appending the line with an operating-system-specific line ending.
+ *
+ * Throws WriteException on error.
+ */
void writeLine(char[] s);
- // writes a Unicode line, throws WriteException on error
+ /***
+ * Write a line of text,
+ * appending the line with an operating-system-specific line ending.
+ *
+ * The format is implementation-specific.
+ * Throws WriteException on error.
+ */
void writeLineW(wchar[] s);
- // writes a string, throws WriteException on error
+ /***
+ * Write a string of text.
+ *
+ * Throws WriteException if it could not be fully written.
+ */
void writeString(char[] s);
- // writes a Unicode string, throws WriteException on error
+ /***
+ * Write a string of text.
+ *
+ * The format is implementation-specific.
+ * Throws WriteException if it could not be fully written.
+ */
void writeStringW(wchar[] s);
- // writes data to stream using vprintf() syntax,
- // returns number of bytes written
+ /***
+ * Print a formatted string into the stream using printf-style syntax,
+ * returning the number of bytes written.
+ */
size_t vprintf(char[] format, va_list args);
+ size_t printf(char[] format, ...); /// ditto
- // writes data to stream using printf() syntax,
- // returns number of bytes written
- size_t printf(char[] format, ...);
-
- // writes data to stream using writef() syntax and returns self
+ /***
+ * Print a formatted string into the stream using writef-style syntax.
+ * References: std.format.
+ * Returns: self to chain with other stream commands like flush.
+ */
OutputStream writef(...);
+ OutputStream writefln(...); /// ditto
+ OutputStream writefx(TypeInfo[] arguments, void* argptr, int newline = false); /// ditto
- // writes data with trailing newline and returns self
- OutputStream writefln(...);
+ void flush(); /// Flush pending output if appropriate.
+ void close(); /// Close the stream, flushing output if appropriate.
+ bool isOpen(); /// Return true if the stream is currently open.
+}
- // writes data with optional trailing newline and returns self
- OutputStream writefx(TypeInfo[] arguments, void* argptr, int newline = false);
- void flush();
- void close();
- bool isOpen();
-}
+/***
+ * Stream is the base abstract class from which the other stream classes derive.
+ *
+ * Stream's byte order is the format native to the computer.
+ *
+ * Reading:
+ * These methods require that the readable flag be set.
+ * Problems with reading result in a ReadException being thrown.
+ * Stream implements the InputStream interface in addition to the
+ * readBlock method.
+ *
+ * Writing:
+ * These methods require that the writeable flag be set. Problems with writing
+ * result in a WriteException being thrown. Stream implements the OutputStream
+ * interface in addition to the following methods:
+ * writeBlock
+ * copyFrom
+ * copyFrom
+ *
+ * Seeking:
+ * These methods require that the seekable flag be set.
+ * Problems with seeking result in a SeekException being thrown.
+ * seek, seekSet, seekCur, seekEnd, position, size, toString, toHash
+ */
-// base class for all streams; not really abstract,
-// but its instances will do nothing useful
+// not really abstract, but its instances will do nothing useful
class Stream : InputStream, OutputStream {
private import std.string, crc32, std.c.stdlib, std.c.stdio;
// stream abilities
- bit readable = false;
- bit writeable = false;
- bit seekable = false;
- protected bit isopen = true;
-
- // flag that last readBlock resulted in eof
- protected bit readEOF = false;
-
- // flag that last getc got \r
- protected bit prevCr = false;
+ bit readable = false; /// Indicates whether this stream can be read from.
+ bit writeable = false; /// Indicates whether this stream can be written to.
+ bit seekable = false; /// Indicates whether this stream can be seeked within.
+ protected bit isopen = true; /// Indicates whether this stream is open.
+
+ protected bit readEOF = false; /// Indicates whether this stream is at eof
+ /// after the last read attempt.
+
+ protected bit prevCr = false; /// For a non-seekable stream indicates that
+ /// the last readLine or readLineW ended on a
+ /// '\r' character.
this() {}
- // reads block of data of specified size,
- // returns actual number of bytes read
- // returning 0 indicates end-of-file
+ /***
+ * Read up to size bytes into the buffer and return the number of bytes
+ * actually read. A return value of 0 indicates end-of-file.
+ */
abstract size_t readBlock(void* buffer, size_t size);
// reads block of data of specified size,
@@ -879,8 +1017,10 @@
// returns estimated number of bytes available for immediate reading
size_t available() { return 0; }
- // writes block of data of specified size,
- // returns actual number of bytes written
+ /***
+ * Write up to size bytes from buffer in the stream, returning the actual
+ * number of bytes that were written.
+ */
abstract size_t writeBlock(void* buffer, size_t size);
// writes block of data of specified size,
@@ -1037,8 +1177,11 @@
return this;
}
- // copies all data from given stream into this one,
- // may throw ReadException or WriteException on failure
+ /***
+ * Copies all data from s into this stream.
+ * This may throw ReadException or WriteException on failure.
+ * This restores the file position of s so that it is unchanged.
+ */
void copyFrom(Stream s) {
if (seekable) {
ulong pos = s.position();
@@ -1054,8 +1197,11 @@
}
}
- // copies specified number of bytes from given stream into
- // this one, may throw ReadException or WriteException on failure
+ /***
+ * Copy a specified number of bytes from the given stream into this one.
+ * This may throw ReadException or WriteException on failure.
+ * Unlike the previous form, this doesn't restore the file position of s.
+ */
void copyFrom(Stream s, ulong count) {
ubyte[128] buf;
while (count > 0) {
@@ -1066,26 +1212,37 @@
}
}
- // moves pointer to given position, relative to beginning of stream,
- // end of stream, or current position, returns new position
+ /***
+ * Change the current position of the stream. whence is either SeekPos.Set, in
+ which case the offset is an absolute index from the beginning of the stream,
+ SeekPos.Current, in which case the offset is a delta from the current
+ position, or SeekPos.End, in which case the offset is a delta from the end of
+ the stream (negative or zero offsets only make sense in that case). This
+ returns the new file position.
+ */
abstract ulong seek(long offset, SeekPos whence);
- // seek from the beginning of the stream.
+ /***
+ * Aliases for their normal seek counterparts.
+ */
ulong seekSet(long offset) { return seek (offset, SeekPos.Set); }
+ ulong seekCur(long offset) { return seek (offset, SeekPos.Current); } /// ditto
+ ulong seekEnd(long offset) { return seek (offset, SeekPos.End); } /// ditto
- // seek from the current point in the stream.
- ulong seekCur(long offset) { return seek (offset, SeekPos.Current); }
-
- // seek from the end of the stream.
- ulong seekEnd(long offset) { return seek (offset, SeekPos.End); }
-
- // sets position
+ /***
+ * Sets file position. Equivalent to calling seek(pos, SeekPos.Set).
+ */
void position(ulong pos) { seek(pos, SeekPos.Set); }
- // returns current position
+ /***
+ * Returns current file position. Equivalent to seek(0, SeekPos.Current).
+ */
ulong position() { return seek(0, SeekPos.Current); }
- // returns size of stream
+ /***
+ * Retrieve the size of the stream in bytes.
+ * The stream must be seekable or a SeekException is thrown.
+ */
ulong size() {
assertSeekable();
ulong pos = position(), result = seek(0, SeekPos.End);
@@ -1120,7 +1277,11 @@
readEOF = prevCr = isopen = readable = writeable = seekable = false;
}
- // creates a string in memory containing copy of stream data
+ /***
+ * Read the entire stream and return it as a string.
+ * If the stream is not seekable the contents from the current position to eof
+ * is read and returned.
+ */
override char[] toString() {
if (!readable)
return super.toString();
@@ -1151,7 +1312,10 @@
return result[0 .. pos];
}
- // calculates CRC-32 of data in stream
+ /***
+ * Get a hash of the stream by reading each byte and using it in a CRC-32
+ * checksum.
+ */
override uint toHash() {
if (!readable || !seekable)
return super.toHash();
@@ -1185,26 +1349,57 @@
}
}
-// Base class for streams that wrap a backing source stream
+/***
+ * A base class for streams that wrap a source stream with additional
+ * functionality.
+ *
+ * The method implementations forward read/write/seek calls to the
+ * source stream. A FilterStream can change the position of the source stream
+ * arbitrarily and may not keep the source stream state in sync with the
+ * FilterStream, even upon flushing and closing the FilterStream. It is
+ * recommended to not make any assumptions about the state of the source position
+ * and read/write state after a FilterStream has acted upon it. Specifc subclasses
+ * of FilterStream should document how they modify the source stream and if any
+ * invariants hold true between the source and filter.
+ */
class FilterStream : Stream {
private Stream s; // source stream
- bit nestClose = true; // close the source when this stream closes
- // Construct a FilterStream around source
+ /// Property indicating when this stream closes to close the source stream as
+ /// well.
+ /// Defaults to true.
+ bit nestClose = true;
+
+ /// Construct a FilterStream for the given source.
this(Stream source) {
s = source;
resetSource();
}
// source getter/setter
+
+ /***
+ * Get the current source stream.
+ */
final Stream source(){return s;}
+
+ /***
+ * Set the current source stream.
+ *
+ * Setting the source stream closes this stream before attaching the new
+ * source. Attaching an open stream reopens this stream and resets the stream
+ * state.
+ */
void source(Stream s) {
close();
this.s = s;
resetSource();
}
- // set this streams state for a new or changed source
+ /***
+ * Indicates the source stream changed state and that this stream should reset
+ * any readable, writeable, seekable, isopen and buffering flags.
+ */
void resetSource() {
if (s !is null) {
readable = s.readable;
@@ -1249,7 +1444,15 @@
override void flush() { super.flush(); s.flush(); }
}
-// A stream that wraps a source stream in a buffer
+/***
+ * This subclass is for buffering a source stream.
+ *
+ * A buffered stream must be
+ * closed explicitly to ensure the final buffer content is written to the source
+ * stream. The source stream position is changed according to the block size so
+ * reading or writing to the BufferedStream may not change the source stream
+ * position by the same amount.
+ */
class BufferedStream : FilterStream {
ubyte[] buffer; // buffer, if any
uint bufferCurPos; // current position in buffer
@@ -1276,6 +1479,10 @@
const uint DefaultBufferSize = 8192;
+ /***
+ * Create a buffered stream for the stream source with the buffer size
+ * bufferSize.
+ */
this(Stream source, uint bufferSize = DefaultBufferSize) {
super(source);
if (bufferSize)
@@ -1534,14 +1741,15 @@
}
}
-// generic File error, base class for all
-// other File exceptions
+/// An exception for File errors.
class StreamFileException: StreamException {
+ /// Construct a StreamFileException with given error message.
this(char[] msg) { super(msg); }
}
-// thrown when unable to open file
+/// An exception for errors during File.open.
class OpenException: StreamFileException {
+ /// Construct an OpenFileException with given error message.
this(char[] msg) { super(msg); }
}
@@ -1565,7 +1773,7 @@
alias int HANDLE;
}
-// just a file on disk without buffering
+/// This subclass is for unbuffered file system streams.
class File: Stream {
version (Win32) {
@@ -1600,11 +1808,26 @@
}
}
- // opens file in requested mode
+ /***
+ * Create the stream with no open file, an open file in read mode, or an open
+ * file with explicit file mode.
+ * mode, if given, is a combination of FileMode.In
+ * (indicating a file that can be read) and FileMode.Out (indicating a file
+ * that can be written).
+ * Opening a file for reading that doesn't exist will error.
+ * Opening a file for writing that doesn't exist will create the file.
+ * The FileMode.OutNew mode will open the file for writing and reset the
+ * length to zero.
+ * The FileMode.Append mode will open the file for writing and move the
+ * file position to the end of the file.
+ */
this(char[] filename, FileMode mode = FileMode.In) { this(); open(filename, mode); }
- // opens file in requested mode
+ /***
+ * Open a file for the stream, in an identical manner to the constructors.
+ * If an error occurs an OpenException is thrown.
+ */
void open(char[] filename, FileMode mode = FileMode.In) {
close();
int access, share, createMode;
@@ -1669,18 +1892,18 @@
}
}
- // creates file for writing
+ /// Create a file for writing.
void create(char[] filename) {
create(filename, FileMode.OutNew);
}
- // creates file in requested mode
+ /// ditto
void create(char[] filename, FileMode mode) {
close();
open(filename, mode | FileMode.OutNew);
}
- // closes file, if it is open; otherwise, does nothing
+ /// Close the current file if it is open; otherwise it does nothing.
override void close() {
if (isopen) {
super.close();
@@ -1751,6 +1974,11 @@
return result;
}
+ /***
+ * For a seekable file returns the difference of the size and position and
+ * otherwise returns 0.
+ */
+
override size_t available() {
if (seekable) {
ulong lavail = size - position;
@@ -1839,7 +2067,13 @@
}
}
-// a buffered file on disk
+/***
+ * This subclass is for buffered file system streams.
+ *
+ * It is a convenience class for wrapping a File in a BufferedStream.
+ * A buffered stream must be closed explicitly to ensure the final buffer
+ * content is written to the file.
+ */
class BufferedFile: BufferedStream {
// opens file for reading
@@ -1926,7 +2160,14 @@
}
-enum BOM { UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE }
+/// UTF byte-order-mark signatures
+enum BOM {
+ UTF8, /// UTF-8
+ UTF16LE, /// UTF-16 Little Endian
+ UTF16BE, /// UTF-16 Big Endian
+ UTF32LE, /// UTF-32 Little Endian
+ UTF32BE, /// UTF-32 Big Endian
+}
private const int NBOMS = 5;
Endian[NBOMS] BOMEndian =
@@ -1943,21 +2184,43 @@
[0x00, 0x00, 0xFE, 0xFF]
];
-// A stream that wraps a source stream with endian support
+
+/***
+ * This subclass wraps a stream with big-endian or little-endian byte order
+ * swapping.
+ *
+ * UTF Byte-Order-Mark (BOM) signatures can be read and deduced or
+ * written.
+ * Note that an EndianStream should not be used as the source of another
+ * FilterStream since a FilterStream call the source with byte-oriented
+ * read/write requests and the EndianStream will not perform any byte swapping.
+ * The EndianStream reads and writes binary data (non-getc functions) in a
+ * one-to-one
+ * manner with the source stream so the source stream's position and state will be
+ * kept in sync with the EndianStream if only non-getc functions are called.
+ */
class EndianStream : FilterStream {
- Endian endian; // endianness of the source stream
- // Construct an Endian stream with specified endianness, defaulting
- // to the native endiannes.
+ Endian endian; /// Endianness property of the source stream.
+
+ /***
+ * Create the endian stream for the source stream source with endianness end.
+ * The default endianness is the native byte order.
+ * The Endian type is defined
+ * in the std.system module.
+ */
this(Stream source, Endian end = std.system.endian) {
super(source);
endian = end;
}
- /* Return -1 if no BOM and otherwise read the BOM and return it.
- * If there is no BOM then the bytes read are pushed back onto
- * the ungetc buffer or ungetcw buffer. Pass ungetCharSize == 2
- * to use ungetcw instead of ungetc.
+ /***
+ * Return -1 if no BOM and otherwise read the BOM and return it.
+ *
+ * If there is no BOM or if bytes beyond the BOM are read then the bytes read
+ * are pushed back onto the ungetc buffer or ungetcw buffer.
+ * Pass ungetCharSize == 2 to use
+ * ungetcw instead of ungetc when no BOM is present.
*/
int readBOM(int ungetCharSize = 1) {
ubyte[4] BOM_buffer;
@@ -1999,8 +2262,10 @@
return result;
}
- // Correct the byte order of buffer to match native endianness.
- // size must be even
+ /***
+ * Correct the byte order of buffer to match native endianness.
+ * size must be even.
+ */
final void fixBO(void* buffer, uint size) {
if (endian != std.system.endian) {
ubyte* startb = cast(ubyte*)buffer;
@@ -2036,8 +2301,11 @@
}
}
- // Correct the byte order of buffer in blocks repeatedly
- // size must be even
+ /***
+ * Correct the byte order of the given buffer in blocks of the given size and
+ * repeated the given number of times.
+ * size must be even.
+ */
final void fixBlockBO(void* buffer, uint size, size_t repeat) {
while (repeat--) {
fixBO(buffer,size);
@@ -2091,7 +2359,7 @@
return result;
}
- // Write the specified BOM to the source stream
+ /// Write the specified BOM b to the source stream.
void writeBOM(BOM b) {
ubyte[] bom = ByteOrderMarks[b];
writeBlock(bom,bom.length);
@@ -2210,14 +2478,20 @@
}
}
-// Parameterized stream class that wraps an array-like type.
-// The Buffer type must support .length, opIndex and opSlice
+/***
+ * Parameterized subclass that wraps an array-like buffer with a stream
+ * interface.
+ *
+ * The type Buffer must support the length property, opIndex and opSlice.
+ * Compile in release mode when directly instantiating a TArrayStream to avoid
+ * link errors.
+ */
class TArrayStream(Buffer): Stream {
Buffer buf; // current data
ulong len; // current data length
ulong cur; // current file position
- // use this buffer, non-copying.
+ /// Create the stream for the the buffer buf. Non-copying.
this(Buffer buf) {
super ();
this.buf = buf;
@@ -2278,7 +2552,7 @@
override size_t available () { return len - cur; }
- // returns pointer to stream data
+ /// Get the current memory data in total.
ubyte[] data() {
if (len > size_t.max)
throw new StreamException("Stream too big");
@@ -2317,22 +2591,22 @@
assert (m.size () == 100);
}
-// virtual stream residing in memory
+/// This subclass reads and constructs an array of bytes in memory.
class MemoryStream: TArrayStream!(ubyte[]) {
+ /// Create the output buffer and setup for reading, writing, and seeking.
// clear to an empty buffer.
this() { this(cast(ubyte[]) null); }
- // use this buffer, non-copying.
+ /***
+ * Create the output buffer and setup for reading, writing, and seeking.
+ * Load it with specific input data.
+ */
this(ubyte[] buf) { super (buf); }
+ this(byte[] buf) { this(cast(ubyte[]) buf); } /// ditto
+ this(char[] buf) { this(cast(ubyte[]) buf); } /// ditto
- // use this buffer, non-copying.
- this(byte[] buf) { this(cast(ubyte[]) buf); }
-
- // use this buffer, non-copying.
- this(char[] buf) { this(cast(ubyte[]) buf); }
-
- // ensure the stream can hold this many bytes.
+ /// Ensure the stream can hold count bytes.
void reserve(size_t count) {
if (cur + count > buf.length)
buf.length = (cur + count) * 2;
@@ -2390,9 +2664,14 @@
}
import std.mmfile;
-// stream wrapping memory-mapped files
+
+/***
+ * This subclass wraps a memory-mapped file with the stream API.
+ * See std.mmfile module.
+ */
class MmFileStream : TArrayStream!(MmFile) {
+ /// Create stream wrapper for file.
this(MmFile file) {
super (file);
MmFile.Mode mode = file.mode;
@@ -2445,8 +2724,16 @@
std.file.remove("testing.txt");
}
-// slices off a portion of another stream, making seeking
-// relative to the boundaries of the slice.
+
+/***
+ * This subclass slices off a portion of another stream, making seeking relative
+ * to the boundaries of the slice.
+ *
+ * It could be used to section a large file into a
+ * set of smaller files, such as with tar archives. Reading and writing a
+ * SliceStream does not modify the position of the source stream if it is
+ * seekable.
+ */
class SliceStream : FilterStream {
private {
ulong pos; // our position relative to low
@@ -2455,7 +2742,13 @@
bit bounded; // upper-bounded by high.
}
- // set the s stream and the low offset but leave the high unbounded.
+ /***
+ * Indicate both the source stream to use for reading from and the low part of
+ * the slice.
+ *
+ * The high part of the slice is dependent upon the end of the source
+ * stream, so that if you write beyond the end it resizes the stream normally.
+ */
this (Stream s, ulong low)
in {
assert (low <= s.size ());
@@ -2467,7 +2760,12 @@
this.bounded = false;
}
- // set the source stream, the low offset, and the high offset.
+ /***
+ * Indicate the high index as well.
+ *
+ * Attempting to read or write past the high
+ * index results in the end being clipped off.
+ */
this (Stream s, ulong low, ulong high)
in {
assert (low <= high);
diff -uNr dmd-0.131/dmd/src/phobos/std_boilerplate.html dmd-0.132/dmd/src/phobos/std_boilerplate.html
--- dmd-0.131/dmd/src/phobos/std_boilerplate.html 1970-01-01 01:00:00.000000000 +0100
+++ dmd-0.132/dmd/src/phobos/std_boilerplate.html 2005-09-19 17:54:38.000000000 +0200
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+
+Digital Mars - The D Programming Language - $(TITLE)
+
+
+
+
+
+
+Home
+| Search
+| D
+| Comments
+
+
+Last update $(DATETIME)
+
+