D - Updated Doxygen: D support
- Hauke Duden (11/11) Jan 02 2004 I have done some hacking on doxygen to add support for D.
- Hauke Duden (13/24) Jan 02 2004 I've updated dfilter.d as suggested above (I also had to make some
- Matthew (12/409) Jan 02 2004 Any chance of you posting / emailing me the original file, as I've lost ...
- Hauke Duden (6/6) Jan 03 2004 Yaneurao (another D-fan from Japan) was kind enough to put a ZIP file on...
I have done some hacking on doxygen to add support for D. The advantange to the old dfilter.exe is that now D constructs that do not exist in C++ are documented better (most importantly: interfaces are interfaces, not classes). There are still some things missing, like support for the /+ +/ comments and unittests,preconditions,postconditions... Maybe this should be combined with an updated dfilter that does a little LESS filtering, to get the best of both worlds. I have attached the patch file for doxygen's scanner.l file (diffed to doxygen 1.3.5). Hauke
Jan 02 2004
Hauke Duden wrote:I have done some hacking on doxygen to add support for D. The advantange to the old dfilter.exe is that now D constructs that do not exist in C++ are documented better (most importantly: interfaces are interfaces, not classes). There are still some things missing, like support for the /+ +/ comments and unittests,preconditions,postconditions... Maybe this should be combined with an updated dfilter that does a little LESS filtering, to get the best of both worlds.I've updated dfilter.d as suggested above (I also had to make some changes so that it compiles with the most recent version of DMD). Combined with the doxygen patch this creates pretty good documentation support. The source file is attached. Hauke P.S.: Because of their size I don't want to post the binaries (dfilter.exe and doxygen.exe) in this newsgroup. If anyone wants them just send me an email... P.P.S.: I have emailed Dimitri van Heesch and he has replied that the patch will probably be included in the official Doxygen distribution. I see good times for D docs ;)
Jan 02 2004
Any chance of you posting / emailing me the original file, as I've lost my original, and I'm keen to merge your changes with mine? Cheers The Yuletide Log "Hauke Duden" <H.NS.Duden gmx.net> wrote in message news:bt4flf$bqt$1 digitaldaemon.com...Hauke Duden wrote:---------------------------------------------------------------------------- ----I have done some hacking on doxygen to add support for D. The advantange to the old dfilter.exe is that now D constructs that do not exist in C++ are documented better (most importantly: interfaces are interfaces, not classes). There are still some things missing, like support for the /+ +/ comments and unittests,preconditions,postconditions... Maybe this should be combined with an updated dfilter that does a little LESS filtering, to get the best of both worlds.I've updated dfilter.d as suggested above (I also had to make some changes so that it compiles with the most recent version of DMD). Combined with the doxygen patch this creates pretty good documentation support. The source file is attached. Hauke P.S.: Because of their size I don't want to post the binaries (dfilter.exe and doxygen.exe) in this newsgroup. If anyone wants them just send me an email... P.P.S.: I have emailed Dimitri van Heesch and he has replied that the patch will probably be included in the official Doxygen distribution. I see good times for D docs ;)import std.file, std.ctype, std.c.stdio; char [] data; /* Data. */ char *c; /* Current point. */ char *s; /* Previous filter point. */ char *e; /* End of the data. */ char *p; /* Start of this token. */ /* Read in a token. */ char [] token () { restart: p = c; if (c >= e) return null; if (isalpha (*c) || *c == '_') { for (c ++; c < e; c ++) if (!isalnum (*c) && *c != '_') break; return p [0 .. (int) (c - p)]; } if (*c == ' ' || *c == '\r' || *c == '\n' || *c == '\t') { c ++; goto restart; } if (*c == '"') { for (c ++; c < e; c ++) if (*c == '\\') c ++; else if (*c == '"') { c ++; break; } goto restart; } if (*c == '\'') { for (c ++; c < e; c ++) if (*c == '\'') { c ++; break; } goto restart; } if (c < e - 1) { if (*c == '/' && c [1] == '/') { for (c += 2; ; c ++) if (c >= e || *c == '\n') { c ++; goto restart; } } if (*c == '/' && c [1] == '*') { for (c += 2; ; c ++) if (c >= e - 1 || (*c == '*' && c [1] == '/')) { c += 2; goto restart; } } if (*c == '/' && c [1] == '+') { int depth = 1; for (c += 2; ; c ++) if (c >= e - 1) goto restart; else if (*c == '/' && c [1] == '+') { c += 2; depth ++; } else if (*c == '+' && c [1] == '/') { c += 2; depth --; if (!depth) goto restart; } } } c ++; return p [0 .. 1]; } /* Print all text to this point and set s to the current point. */ void flush (char *p) { fwrite (s, (int) (p - s), 1, stdout); s = c; } /* Consume a "{ ... }" or "(xxx) { ... }" block. */ void skipBlock (char *p) { char *o = s; flush (p); int depth = 0; char [] t = token (); if (t == "(") { while (1) { t = token (); if (t == ")" || t == null) break; } t = token (); } if (t != "{") { s = p; flush (c); return; } while (1) { if (t == null) break; if (t == "{") depth ++; if (t == "}") { depth --; if (depth == 0) break; } t = token (); } s = c; } int main (char [] [] args) { if (args.length == 1) { printf ("%.*s FILENAME\n\nPreprocesses the file in preparation forDoxygen.\n", args [0]);return 1; } data = (char []) read (args [1]); c = s = data; e = s + data.length; char [] t; char [] [] protectRecord; char [] protect = "public"; char [] [] brackets; char [] nextOpenBracket; char [] nextSemiColon; bit insideBrackets; while (1) { t = token (); if (t == null) { flush (c); return 0; } switch (t) { /* Remove these keywords. */ case "body": flush (p); s = c; break; /* Remove these blocks. */ case "unittest": case "invariant": case "in": case "out": skipBlock (p); break; /* Remove "keyword:" but only if it is followed with a colon.*/case "override": case "abstract": case "final": flush (p); if ((t = token ()) == ":") s = c; break; case ";": flush (c); printf ("%.*s", nextSemiColon); nextSemiColon = null; break; /* "keyword" without "keyword:" into "keyword: ... { ... }antikeyword:" */case "public": case "private": case "protected": flush (p); if (token () == ":") { printf ("%.*s", t); protect = t; break; } if (t != protect) { printf ("%.*s: ", t); s = p; nextOpenBracket = protect ~ ":"; nextSemiColon = protect ~ ":"; } break; /* Modify into "package". */ /*Not necessary anymore case "module": flush (p); printf ("package ", nextSemiColon); s = c; break;*/ /* Modify into import X.Y.*. */ /* Not necessary anymore case "import": flush (p); printf ("import ", nextSemiColon); while ((t = token ()) != null) { if (t == ";") { printf (";"); break; } else printf ("%.*s", t); } s = c; break;*/ /* Remove "extern (...)". */ case "extern": flush (p); if ((t = token ()) != "(") { c = p; break; } while ((t = token ()) != null) if (t == ")") break; s = c; break; /* "alias" into "typedef". */ case "alias": flush (p); printf ("typedef"); s = c; break; /* "instance" into "typedef". */ case "instance": flush (p); printf ("typedef"); s = c; while ((t = token ()) != null) if (t == "(") { flush (p); printf ("<"); s = c; } else if (t == ")") { flush (p); printf (">"); s = c; break; } break; case "{": brackets ~= nextOpenBracket; nextOpenBracket = null; break; /* "}" into "};" */ case "}": if (protectRecord.length) { protect = protectRecord [protectRecord.length - 1]; protectRecord.length = protectRecord.length - 1; } flush (c); printf (";"); if (brackets.length && brackets [brackets.length - 1]) { printf (" %.*s", brackets [brackets.length - 1]); brackets = brackets [0 .. brackets.length - 1]; } break; /* "class ... {" into "class ... { public:". */ /* Not necessary anymore case "class": case "interface": { bit colon = false; flush (p); printf ("class"); protectRecord ~= protect; protect = "public"; while ((t = token ()) != null) { restart: if (t == ":" && !colon) { colon = true; t = token (); if (t != "public" && t != "private" && t !="protected"){ flush (p); s = p; printf ("public "); goto restart; } } else if (t == ";") break; else if (t == "{") { flush (c); printf (" public:"); break; } } break; }*/ /* "template name (x)" into "template namespace name <x>". */ case "template": protectRecord ~= protect; protect = "public"; flush (c); printf (" class"); while ((t = token ()) != null) if (t == "(") { flush (p); printf ("<"); s = c; } else if (t == ")") { flush (p); printf (">"); s = c; break; } while ((t = token ()) != null) if (t == "{") { flush (c); printf (" public:"); break; } else if (t == ";") break; break; /* "delegate (...) name" into "(*name) (...)". */ case "delegate": flush (p); s = c; while ((t = token ()) != null) if (t == ")") { t = token (); printf ("(*%.*s)", t); flush (p); s = c; break; } break; default: break; } } }
Jan 02 2004
Yaneurao (another D-fan from Japan) was kind enough to put a ZIP file on his web site that contains the Doxygen and dfilter binaries, as well as the dfilter source code. Here's a link: http://www.sun-inet.or.jp/~yaneurao/dlang/lib/ddoc.zip Hauke
Jan 03 2004