changeset 717:cb8edb09108a

Updated docgen (mostly) to new tango. Reflective options. Updated translations.
author Jari-Matti M?kel? <jmjm@iki.fi>
date Fri, 01 Feb 2008 15:05:56 +0200
parents 08e6174a2e1c
children be887ada3e3e
files trunk/src/docgen/config/configurator.d trunk/src/docgen/config/reflection.d trunk/src/docgen/document/generator.d trunk/src/docgen/graphutils/dotwriter.d trunk/src/docgen/misc/meta.d trunk/src/docgen/misc/options.d trunk/src/docgen/misc/parser.d trunk/src/docgen/page/htmlwriter.d trunk/src/docgen/page/writer.d trunk/src/docgen/sourcelisting/latexwriter.d trunk/src/docgen/tests/graphs.d trunk/src/docgen/testsuite.d trunk/src/lang_fi.d
diffstat 13 files changed, 433 insertions(+), 146 deletions(-) [+]
line wrap: on
line diff
--- a/trunk/src/docgen/config/configurator.d	Thu Jan 31 21:31:47 2008 +0100
+++ b/trunk/src/docgen/config/configurator.d	Fri Feb 01 15:05:56 2008 +0200
@@ -5,6 +5,7 @@
 module docgen.config.configurator;
 
 import docgen.config.reader;
+import docgen.config.reflection;
 import docgen.misc.options;
 
 import Integer = tango.text.convert.Integer;
@@ -26,59 +27,9 @@
   DocGeneratorOptions *getConfiguration();
 }
 
-// ugly piece of crap begins.
-
-char[] _wrong(char[] key) {
-  return `if (val.length != 1) throw new Exception(
-    "Wrong number of arguments for `~key~`");`;
-}
-
-char[] _switch(char[] stuff) {
-  return "switch(key) {" ~ stuff ~ "}";
-}
-
-char[] _parseI(char[] key) {
-  return `case "` ~ key ~ `":` ~ _wrong(key) ~ key ~
-    "= Integer.parse(val[0]); continue;";
-}
-
-char[] _parseS(char[] key) {
-  return `case "` ~ key ~ `":` ~ _wrong(key) ~ key ~
-    "= val[0]; continue;";
-}
-
-char[] _parseB(char[] key) {
-  return `case "` ~ key ~ `":` ~ _wrong(key) ~ key ~
-    `= val[0] == "true" ? true : val[0] == "false" ? false : err(); continue;`;
-}
-
-char[] _parseList(char[] key) {
-  return `case "` ~ key ~ `":foreach(v; val) ` ~
-    key ~ `~= v; continue;`;
-}
-
-template _parseEnum_(bool list, char[] key, V...) {
-  static if (V.length>1)
-    const char[] _parseEnum_ =
-      `case "` ~ V[0] ~ `":` ~ key ~ (list ? "~" : "") ~ `=` ~ V[1] ~ `; continue;` \n ~
-      _parseEnum_!(list, key, V[2..$]);
-  else
-    const char[] _parseEnum_ = "";
-}
-
-template _parseEnum(char[] key, V...) {
-  const char[] _parseEnum = `case "` ~ key ~
-    `":` ~ _wrong(key) ~ `switch(val[0]) {` ~
-    _parseEnum_!(false, key, V) ~
-      `default: err(); } continue;`;
-}
-
-template _parseEnumList(char[] key, V...) {
-  const char[] _parseEnumList = `case "` ~ key ~
-    `":` ~ `foreach (item; val) switch(item) {` ~
-    _parseEnum_!(true, key, V) ~
-      `default: err(); } continue;`;
-}
+private DocGeneratorOptions options;
+private Struct!(options) opt;
+private const cases = makeTypeStringForStruct!(opt);
 
 class DefaultConfigurator : Configurator {
   private:
@@ -116,49 +67,9 @@
           "=" ~ (val.length ? val[0] : "null"));
       }
 
+      // cuteness, lul
       mixin(_switch(
-        _parseEnum!("options.graph.imageFormat",
-          "PDF", "ImageFormat.PDF",
-          "SVG", "ImageFormat.SVG",
-          "PNG", "ImageFormat.PNG",
-          "GIF", "ImageFormat.GIF"
-        ) ~
-        _parseI("options.graph.depth") ~
-        _parseS("options.graph.nodeColor") ~
-        _parseS("options.graph.cyclicNodeColor") ~
-        _parseS("options.graph.unlocatableNodeColor") ~
-        _parseS("options.graph.depColor") ~
-        _parseS("options.graph.cyclicDepColor") ~
-        _parseS("options.graph.publicDepColor") ~
-        _parseS("options.graph.clusterColor") ~
-        _parseB("options.graph.includeUnlocatableModules") ~
-        _parseB("options.graph.highlightCyclicEdges") ~
-        _parseB("options.graph.highlightCyclicVertices") ~
-        _parseB("options.graph.groupByPackageNames") ~
-        _parseB("options.graph.groupByFullPackageName") ~
-        _parseB("options.listing.literateStyle") ~
-        _parseB("options.listing.enableListings") ~
-        _parseS("options.templates.title") ~
-        _parseS("options.templates.versionString") ~
-        _parseS("options.templates.copyright") ~
-        _parseS("options.templates.paperSize") ~
-        _parseB("options.templates.shortFileNames") ~
-        _parseS("options.templates.templateStyle") ~
-        _parseList("options.parser.importPaths") ~
-        _parseList("options.parser.rootPaths") ~
-        _parseList("options.parser.strRegexps") ~
-        _parseEnum!("options.parser.commentFormat",
-            "Doxygen", "CommentFormat.Doxygen",
-            "Ddoc", "CommentFormat.Ddoc"
-        ) ~
-        _parseI("options.parser.depth") ~
-        _parseEnumList!("options.outputFormats",
-            "LaTeX", "DocFormat.LaTeX",
-            "HTML", "DocFormat.HTML",
-            "XML", "DocFormat.XML",
-            "PlainText", "DocFormat.PlainText"
-        ) ~
-        _parseS("options.outputDir") ~
+        mixin(cases) ~
         `default: throw new Exception("Illegal configuration key " ~ key);`
       ));
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/config/reflection.d	Fri Feb 01 15:05:56 2008 +0200
@@ -0,0 +1,275 @@
+/**
+ * Author: Jari-Matti Mäkelä
+ * License: GPL3
+ */
+module docgen.config.reflection;
+
+import docgen.misc.meta;
+import docgen.misc.options;
+
+////
+//
+// Macros for reading input
+//
+////
+
+char[] _wrong(char[] key) {
+  return `if (val.length != 1) throw new Exception(
+    "Wrong number of arguments for `~key~`");`;
+}
+
+char[] _switch(char[] stuff) {
+  return "switch(key) {" ~ stuff ~ "}";
+}
+
+char[] _parseI(char[] key) {
+  return `case "` ~ key ~ `":` ~ _wrong(key) ~ key ~
+    `= Integer.parse(val[0]); continue;`;
+}
+
+char[] _parseS(char[] key) {
+  return `case "` ~ key ~ `":` ~ _wrong(key) ~ key ~
+    `= val[0]; continue;`;
+}
+
+char[] _parseB(char[] key) {
+  return `case "` ~ key ~ `":` ~ _wrong(key) ~ key ~
+    `= val[0] == "true" ? true : val[0] == "false" ? false : err(); continue;`;
+}
+
+char[] _parseList(char[] key) {
+  return `case "` ~ key ~ `":foreach(v; val) ` ~
+    key ~ `~= v; continue;`;
+}
+
+template _parseEnum_(bool list, char[] key, V...) {
+  static if (V.length>1)
+    const char[] _parseEnum_ =
+      `case "` ~ V[0] ~ `":` ~ key ~ (list ? "~" : "") ~ `=` ~ V[1] ~ `; continue;` \n ~
+      _parseEnum_!(list, key, V[2..$]);
+  else
+    const char[] _parseEnum_ = "";
+}
+
+template _parseEnum(char[] key, V...) {
+  const char[] _parseEnum = `case "` ~ key ~
+    `":` ~ _wrong(key) ~ `switch(val[0]) {` ~
+    _parseEnum_!(false, key, V) ~
+      `default: err(); } continue;`;
+}
+
+template _parseEnumList(char[] key, V...) {
+  const char[] _parseEnumList = `case "` ~ key ~
+    `":` ~ `foreach (item; val) switch(item) {` ~
+    _parseEnum_!(true, key, V) ~
+      `default: err(); } continue;`;
+}
+
+////
+//
+// Reflection for properties. This code will hopefully get better when the dmdfe bugs get fixed.
+//
+////
+
+// dmdfe bug -- Seriously WTF?
+char[] fixType(char[] type) {
+  return type[$-1] == ' ' ? type[0..$-1] : type;
+}
+
+// take the last part of field name
+char[] getLastName(char[] field) {
+  if (field.length == 0) return "";
+  int t = 0;
+  // dmdfe bug: a while loop causes index out of bounds error
+  for (int i=field.length-1; i >= 0; i--)
+    if (field[i] == '.') { t = i+1; break; }
+  return field[t..$];
+}
+
+// dmdfe bug: cannot return evalType alias
+template _evalType(char[] type) {
+  mixin("alias "~type~" value;");
+}
+
+// Note: stuple wrappers needed for tuples, otherwise:
+// dmdfe bug: cc1d: ../.././gcc/d/dmd/expression.c:4865: virtual Expression* DotIdExp::semantic(Scope*): Assertion `0' failed.
+template evalType(char[] type) {
+  alias _evalType!(type).value evalType;
+}
+
+// wraps the reflected struct and enum data inside struct because otherwise the handling becomes impossibly hard
+template getType(T) {
+  static if(is(T == struct))
+    alias Struct!(T) getType;
+  else static if(is(T == enum))
+    alias Enum!(T) getType;
+  else static if(isEnumList!(T))
+    alias Enum!(enumListType!(T), true) getType;
+  else
+    alias T getType;
+}
+
+template getTypes(alias S, int idx = S.tupleof.length) {
+  static if(idx)
+    alias Tuple!(getTypes!(S, idx-1), getType!(typeof(S.tupleof[idx-1]))) getTypes;
+  else
+    alias Tuple!() getTypes;
+}
+
+/**
+ * Extracts the comma separated struct field names using .tupleof.stringof.
+ * This is needed since the struct.tupleof[n].stringof is broken for enums and tuples in dmdfe.
+ *
+ * Bugs: handling of tuples
+ */
+char[] __getNames(char[] type) {
+  char[] tmp;
+  bool end = false;
+
+  foreach(c; type[5..$]) {
+    if (c != ' ' && c != '(' && c != ')' && end) tmp ~= c;
+    if (c == ',') end = false;
+    if (c == '.') end = true;
+  }
+
+  return tmp;
+}
+
+template _getNames(char[] str, T...) {
+  static if (str.length) {
+    static if (str[0] == ',')
+      alias _getNames!(str[1..$], T, "") _getNames;
+    else
+      alias _getNames!(str[1..$], T[0..$-1], T[$-1] ~ str[0]) _getNames;
+  } else
+    alias T _getNames;
+}
+
+template getNames(char[] str) {
+  alias _getNames!(__getNames(str), "") getNames;
+}
+
+struct Struct(alias T) {
+  const type = "struct"; // used for pattern matching... apparently there's no other way
+  const name = fixType(T.stringof); // dmdfe bug: trailing space
+  alias STuple!(getNames!(T.tupleof.stringof)) names;
+  alias STuple!(getTypes!(T)) types;
+}
+
+struct Enum(alias T, bool list = false) {
+  const type = list ? "enumlist" : "enum"; // used for pattern matching... apparently there's no other way
+  const name =  T.stringof[1..$]; // dmdfe bug: returns enum base type instead enum type
+  alias evalType!("___"~name).tuple elements;
+}
+
+// determines the enumtype[] type
+template isEnumList(T : T[]) {
+  const isEnumList = T.stringof[0] == '_';
+}
+
+template isEnumList(T) {
+  const isEnumList = false;
+}
+
+template enumListType(T : T[]) {
+  alias T enumListType;
+}
+
+template enumListType(T) {
+  static assert(false, "Not enum list type!");
+}
+
+char[] createIParser(char[] field) {
+  return `_parseI("` ~ field ~ `") ~` \n;
+}
+
+char[] createBParser(char[] field) {
+  return `_parseB("` ~ field ~ `") ~` \n;
+}
+ 
+char[] createSParser(char[] field) {
+  return `_parseS("` ~ field ~ `") ~` \n;
+}
+ 
+char[] createLParser(char[] field) {
+  return `_parseList("` ~ field ~ `") ~` \n;
+}
+
+char[] createEParser(char[] field, char[] contents) {
+  return `_parseEnum!("` ~ field ~ `",` ~ contents ~ `) ~` \n;
+}
+
+char[] createELParser(char[] field, char[] contents) {
+  return `_parseEnumList!("` ~ field ~ `",` ~ contents ~ `) ~` \n;
+}
+
+template _makeEnumString(char[] t, E...) {
+  static if (E.length)
+    const _makeEnumString = `"` ~ E[0] ~ `", "` ~ t ~ "." ~ E[0] ~ `",` ~
+                            _makeEnumString!(t, E[1..$]);
+  else
+    const _makeEnumString = "";
+}
+
+// avoids the following dmdfe bugs:
+//  - Error: elements is not a type (typeof(T).elements)
+//  - Error: tuple is not a valid template value argument (T.elements where T is the complex type def)
+template makeEnumString(char[] t, T) {
+  const makeEnumString = _makeEnumString!(t, T.elements);
+}
+
+/**
+ * Generates code for parsing data from the configuration data structure.
+ */
+template makeTypeString(int i, N, T, char[] prefix) {
+  static assert(N.tuple.length == T.tuple.length);
+  static if (i < N.tuple.length) {
+    static if (is(T.tuple[i] == bool))
+      const makeTypeString = createBParser(prefix ~ N.tuple[i]) ~ makeTypeString!(i+1, N, T, prefix);
+    else static if (is(T.tuple[i] : int))
+      const makeTypeString = createIParser(prefix ~ N.tuple[i]) ~ makeTypeString!(i+1, N, T, prefix);
+    else static if (is(T.tuple[i] == char[]))
+      const makeTypeString = createSParser(prefix ~ N.tuple[i]) ~ makeTypeString!(i+1, N, T, prefix);
+    else static if (is(T.tuple[i] == char[][]))
+      const makeTypeString = createLParser(prefix ~ N.tuple[i]) ~ makeTypeString!(i+1, N, T, prefix);
+    else static if (is(T.tuple[i] == struct)) {
+      static if (T.tuple[i].type == "struct")
+        const makeTypeString = makeTypeString!(0, typeof(T.tuple[i].names),
+                               typeof(T.tuple[i].types), prefix~N.tuple[i]~".") ~
+                               makeTypeString!(i+1, N, T, prefix);
+      else static if (T.tuple[i].type == "enum")
+        const makeTypeString = createEParser(prefix ~ N.tuple[i],
+                               makeEnumString!(T.tuple[i].name, T.tuple[i])[0..$-1]) ~
+                               makeTypeString!(i+1, N, T, prefix);
+      else static if (T.tuple[i].type == "enumlist")
+        const makeTypeString = createELParser(prefix ~ N.tuple[i],
+                               makeEnumString!(T.tuple[i].name, T.tuple[i])[0..$-1]) ~
+                               makeTypeString!(i+1, N, T, prefix);
+      else {
+        const makeTypeString = "?" ~ makeTypeString!(i+1, N, T, prefix);
+        static assert(false, "Unknown type");
+      }
+    } else {
+      const makeTypeString = "?" ~ makeTypeString!(i+1, N, T, prefix);
+      static assert(false, "Unknown type");
+    }
+  } else
+    const makeTypeString = "";
+}
+
+template makeTypeStringForStruct(alias opt) {
+  const makeTypeStringForStruct = makeTypeString!(0, opt.names, opt.types, opt.name~".")[0..$-2];
+}
+
+/* some leftovers 
+template handleType(T, char[] prefix="") {
+  static if(is(typeof(T) == struct)) {
+    static if(T.type == "enum")
+      // another dmdfe weirdness: T.stringof == "Enum!(Type)" here, but if do
+      // alias T handleType;, the result.stringof is "struct Enum".
+      alias T handleType;
+  } else
+    alias T handleType;
+}
+*/
+
--- a/trunk/src/docgen/document/generator.d	Thu Jan 31 21:31:47 2008 +0100
+++ b/trunk/src/docgen/document/generator.d	Fri Feb 01 15:05:56 2008 +0200
@@ -89,7 +89,7 @@
     scan(templateDir~options.templates.templateStyle~"/"~formatDirs[docFormat]~"/static/");
 
     foreach(filePath; scan.files) {
-      (new FilePath(outPath(filePath.file))).copy(filePath.toUtf8());
+      (new FilePath(outPath(filePath.file))).copy(filePath.toString());
     }
 
     debug Stdout(scan.files.length)(" static files copied.\n");
--- a/trunk/src/docgen/graphutils/dotwriter.d	Thu Jan 31 21:31:47 2008 +0100
+++ b/trunk/src/docgen/graphutils/dotwriter.d	Fri Feb 01 15:05:56 2008 +0200
@@ -127,7 +127,7 @@
         
   void generateImageTag(OutputStream imageFile) {
     // name of the .dot file
-    char[] fn = (cast(Object)imageFile.conduit).toUtf8();
+    char[] fn = (cast(Object)imageFile.conduit).toString();
     fn = FilePath(fn).file;
 
     fn = fn[0..$-3] ~ imageFormatExts[factory.options.graph.imageFormat];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/misc/meta.d	Fri Feb 01 15:05:56 2008 +0200
@@ -0,0 +1,98 @@
+/**
+ * Author: Jari-Matti Mäkelä
+ * License: GPL3
+ */
+module docgen.misc.meta;
+
+/// tuple literal workaround
+template Tuple(T...) { alias T Tuple; }
+
+/// another tuple literal workaround (can be nested & avoids at least one dmdfe bug)
+struct STuple(T...) { alias T tuple; }
+
+
+// (a -> b), [a] -> [b]
+template map(alias S, T...) {
+  static if (T.length)
+    alias Tuple!(S!(T[0]), map!(S, T[1..$])) map;
+  else
+    alias T map;
+}
+
+/// (a -> Bool), [a] -> [a]
+template filter(alias S, T...) {
+  static if (!T.length)
+    alias Tuple!() filter;
+  else static if (S!(T[0]))
+    alias Tuple!(T[0], filter!(S, T[1..$])) filter;
+  else
+    alias filter!(S, T[1..$]) filter;
+}
+
+/// Int -> Bool
+template odd(int T) {
+  const odd = T%2 == 1;
+}
+
+/// Int -> Bool
+template even(int T) {
+  const even = !odd!(T);
+}
+
+/// a [a] -> a  -- max x y = max2 x (max y)
+T max(T, U...)(T a, U b) {
+  static if (b.length)
+    return a > max(b) ? a : max(b);
+  else
+    return a;
+}
+
+/// a [a] -> a  -- min x y = min2 x (min y)
+T min(T, U...)(T a, U b) {
+  static if (b.length)
+    return a < min(b) ? a : min(b);
+  else
+    return a;
+}
+
+/// Upcasts derivatives of B to B
+template UpCast(B, T) { alias T UpCast; }
+template UpCast(B, T : B) { alias B UpCast; }
+
+/// converts integer to ascii, base 10
+char[] itoa(int i) {
+  char[] ret;
+  auto numbers = "0123456789ABCDEF";
+
+  do {
+    ret = numbers[i%10] ~ ret;
+    i /= 10;
+  } while (i)
+
+  return ret;
+}
+
+/// Enum stuff
+
+template _genList(char[] pre, char[] post, T...) {
+  static if (T.length)
+    const _genList = pre ~ T[0] ~ post ~ (T.length>1 ? "," : "") ~
+                     _genList!(pre, post, T[1..$]);
+  else
+    const _genList = ``;
+}
+
+/**
+ * Creates
+ *   - a typedef for enum (workaround for .tupleof.stringof)
+ *   - the enum structure
+ *   - string array of enum items (for runtime programming)
+ *   - string tuple of enum items (for metaprogramming - char[][] doesn't work)
+ */
+template createEnum(char[] tName, char[] eName, char[] arName, char[] alName, T...) {
+  const createEnum =
+    "typedef int " ~ tName ~ ";" ~
+    "enum " ~ eName ~ ":" ~ tName ~ "{" ~ _genList!("", "", T) ~ "};" ~
+    "char[][] " ~ arName ~ "=[" ~ _genList!(`"`, `"[]`, T) ~ "];" ~
+    "alias STuple!(" ~ _genList!(`"`, `"`, T) ~ ") " ~ alName ~ ";";
+}
--- a/trunk/src/docgen/misc/options.d	Thu Jan 31 21:31:47 2008 +0100
+++ b/trunk/src/docgen/misc/options.d	Fri Feb 01 15:05:56 2008 +0200
@@ -4,13 +4,15 @@
  */
 module docgen.misc.options;
 
+import docgen.misc.meta;
+
+/** creates reflective enums, syntax: enum name + list of elements */
+template optionEnum(char[] name, T...) {
+  const optionEnum = createEnum!("_" ~ name, name, "__" ~ name, "___" ~ name, T);
+}
+
 /** Supported document output formats. */
-enum DocFormat {
-  LaTeX,
-  XML,
-  HTML,
-  PlainText
-}
+mixin(optionEnum!("DocFormat", "LaTeX", "XML", "HTML", "PlainText"));
 
 /**
  * Supported comment formats.
@@ -18,28 +20,16 @@
  * http://www.stack.nl/~dimitri/doxygen/docblocks.html
  * http://www.digitalmars.com/d/ddoc.html
  */
-enum CommentFormat {
-  Ddoc,
-  Doxygen
-}
+mixin(optionEnum!("CommentFormat", "Ddoc", "Doxygen"));
 
 /** Supported image formats. */
-enum ImageFormat {
-  PNG,
-  SVG,
-  GIF,
-  PDF
-}
+mixin(optionEnum!("ImageFormat", "PNG", "SVG", "GIF", "PDF"));
 
 /** Image format extensions. */
 const imageFormatExts = [ "png", "svg", "gif", "pdf" ];
 
 /** Supported graph writers. */
-enum GraphFormat {
-  Dot,
-  ModuleNames,
-  ModulePaths
-}
+mixin(optionEnum!("GraphFormat", "Dot", "ModuleNames", "ModulePaths"));
 
 struct GraphOptions {
   /// image format to use for graphs
@@ -113,7 +103,7 @@
 
   /// list of document formats to be generated
   DocFormat[] outputFormats;
-  
+ 
   GraphOptions graph;
   ListingOptions listing;
   TemplateOptions templates;
--- a/trunk/src/docgen/misc/parser.d	Thu Jan 31 21:31:47 2008 +0100
+++ b/trunk/src/docgen/misc/parser.d	Fri Feb 01 15:05:56 2008 +0200
@@ -4,9 +4,9 @@
  */
 module docgen.misc.parser;
 
-import dil.Parser;
+import dil.parser.Parser;
 import dil.Settings;
-public import dil.Module;
+public import dil.semantic.Module;
 import tango.text.Regex : RegExp = Regex;
 import tango.io.FilePath;
 import tango.text.Util;
@@ -148,10 +148,10 @@
 
             if (loaded_mod !is null) {
               idg(loaded_mod, mod, importList.isPublic());
-            } else if (IncludeUnlocatableModules) {
+            } else if (IncludeUnlocatableModules) {/* FIXME
               auto tmp = new Module(null, true);
               tmp.moduleFQN = replace(moduleFQN_.dup, dirSep, '.');
-              idg(tmp, mod, importList.isPublic());
+              idg(tmp, mod, importList.isPublic());*/
             }
           }
       }
--- a/trunk/src/docgen/page/htmlwriter.d	Thu Jan 31 21:31:47 2008 +0100
+++ b/trunk/src/docgen/page/htmlwriter.d	Fri Feb 01 15:05:56 2008 +0200
@@ -59,7 +59,7 @@
 
     if (name == "stylesheet") {
       styleSheetFile = (new FilePath(
-        (cast(Object)outputs[0].conduit).toUtf8())).file();
+        (cast(Object)outputs[0].conduit).toString())).file();
     }
   }
 
--- a/trunk/src/docgen/page/writer.d	Thu Jan 31 21:31:47 2008 +0100
+++ b/trunk/src/docgen/page/writer.d	Fri Feb 01 15:05:56 2008 +0200
@@ -6,9 +6,11 @@
 
 public import docgen.misc.misc;
 public import docgen.misc.options;
+public import docgen.misc.parser;
 import tango.io.model.IConduit : OutputStream;
-import tango.util.time.Date;
-import tango.util.time.Clock;
+import tango.time.chrono.Gregorian;
+import tango.text.locale.Core;
+import tango.time.WallClock;
 import tango.text.convert.Sprint;
 import tango.io.stream.FileStream;
 import tango.io.Stdout;
@@ -16,7 +18,6 @@
 import tango.text.convert.Layout : Layout;
 import tango.io.FilePath;
 import tango.io.FileScan;
-public import docgen.misc.parser;
 
 const templateDir = "docgen/templates/";
 
@@ -182,7 +183,7 @@
       debug Stdout(scan.files.length)(" template files loaded.\n");
 
       foreach(tpl; scan.files) {
-        m_templates[tpl.name] = loadTemplate(tpl.toUtf8());
+        m_templates[tpl.name] = loadTemplate(tpl.toString());
       }
     }
 
@@ -210,13 +211,21 @@
     }
     
     char[] timeNow() {
-      auto date = Clock.toDate;
+      auto n = WallClock.now;
+      auto c = Gregorian.generic;
+      auto d = c.toDate(n);
       auto sprint = new Sprint!(char);
-      return sprint.format("{0} {1} {2} {3}",
-        date.asDay(),
-        date.asMonth(),
-        date.day,
-        date.year).dup;
+
+      auto culture = new Culture("en-GB");
+      auto dateTimeFormat = culture.dateTimeFormat();
+
+      return sprint.format("{} {} {} {}",
+        dateTimeFormat.getAbbreviatedDayName(c.getDayOfWeek(n)),
+        1,//d.day(),
+        //dateTimeFormat.getAbbreviatedMonthName(d.month()),
+        2,//d.month(),
+        3//d.year()) //FIXME: something is broken here (Error: function expected before (), not *(&d + 8u) of type uint)
+        ).dup;
     }
   }
 }
--- a/trunk/src/docgen/sourcelisting/latexwriter.d	Thu Jan 31 21:31:47 2008 +0100
+++ b/trunk/src/docgen/sourcelisting/latexwriter.d	Fri Feb 01 15:05:56 2008 +0200
@@ -26,7 +26,7 @@
     
     writer.addListing(
       moduleName,
-      FilePath((cast(Object)output.conduit).toUtf8()).file
+      FilePath((cast(Object)output.conduit).toString()).file
     );
   }
 }
--- a/trunk/src/docgen/tests/graphs.d	Thu Jan 31 21:31:47 2008 +0100
+++ b/trunk/src/docgen/tests/graphs.d	Fri Feb 01 15:05:56 2008 +0200
@@ -9,7 +9,7 @@
 import docgen.graphutils.writers;
 import docgen.page.writers;
 import tango.io.FileConduit;
-import dil.Module;
+import dil.semantic.Module;
 
 void saveDefaultGraph(Vertex[] vertices, Edge[] edges, char[] fname) {
   auto gen = new TestDocGenerator;
@@ -22,6 +22,7 @@
   auto gwf = new DefaultGraphWriterFactory(gen);
   auto file = new FileConduit("docgen/teststuff/" ~ fname, FileConduit.WriteCreate);
   auto file2 = new FileConduit("docgen/teststuff/" ~ fname ~ "-2", FileConduit.WriteCreate);
+
   auto writer = gwf.createGraphWriter(
     ddf.createPageWriter( [ file2 ], DocFormat.LaTeX),
     GraphFormat.Dot
--- a/trunk/src/docgen/testsuite.d	Thu Jan 31 21:31:47 2008 +0100
+++ b/trunk/src/docgen/testsuite.d	Fri Feb 01 15:05:56 2008 +0200
@@ -8,6 +8,7 @@
 import docgen.tests.parse;
 import docgen.tests.doctemplate;
 import docgen.tests.listing;
+//import docgen.tests.sexp;
 import tango.io.Stdout;
 
 /**
@@ -17,6 +18,7 @@
  */
 void main() {
   Stdout("Running..");
+
   graph1();
   graph2();
   graph3();
@@ -26,5 +28,6 @@
   parse2();
   doctemplate1();
   listing1();
+//  loadConfig();
   Stdout("done.\n");
 }
--- a/trunk/src/lang_fi.d	Thu Jan 31 21:31:47 2008 +0100
+++ b/trunk/src/lang_fi.d	Fri Feb 01 15:05:56 2008 +0200
@@ -7,7 +7,7 @@
 
 string[] messages = [
   // Lexer messages:
-  "", // TODO: translate
+  "virheellinen merkki: '{0}'",
   "virheellinen Unicode-merkki.",
   "virheellinen UTF-8-merkkijono.",
   // ''
@@ -22,7 +22,7 @@
   // ""
   "päättämätön merkkijonoliteraali.",
   // x""
-  "ei-heksamerkki '{0}' löytyi heksajonossa.",
+  "ei-heksamerkki '{0}' heksajonossa.",
   "pariton määrä heksanumeroita heksajonossa.",
   "päättämätön heksajono.",
   // /* */ /+ +/
@@ -32,12 +32,12 @@
   "päättämätön raakamerkkijono.",
   "päättämätön gravisaksenttimerkkijono.",
   // \x \u \U
-  "löydettiin määrittelemätön escape-sekvenssi.", // TODO: Insert '{0}'
-  "found invalid Unicode escape sequence '{0}'.", // TODO: translate
+  "määrittelemätön escape-sekvenssi {0}.",
+  "virheellinen Unicode escape-merkki '{0}'.",
   "riittämätön määrä heksanumeroita escape-sekvenssissä.",
   // \&[a-zA-Z][a-zA-Z0-9]+;
   "määrittelemätön HTML-entiteetti '{0}'",
-  "päättämätön HTML-entiteetti.", // TODO: insert '{0}'
+  "päättämätön HTML-entiteetti {0}.",
   "HTML-entiteettien tulee alkaa kirjaimella.",
   // integer overflows
   "desimaaliluku ylivuotaa etumerkin.",
@@ -50,19 +50,19 @@
   "virheellinen heksaluku; odotettiin vähintään yhtä heksanumeroa.",
   "virheellinen binääriluku; odotettiin vähintään yhtä binäärinumeroa.",
   "heksadesimaalisen liukuluvun eksponentti vaaditaan.",
-  "heksadesimaalisen liukuluvun eksponentista puuttui numeroita.", // TODO: update
+  "heksadesimaalisen liukuluvun eksponentin tulee alkaa numerolla.",
   "eksponenttien tulee alkaa numerolla.",
 
   // Parser messages
-  "odotettiin '{0}':a, mutta löydettiin '{1}'.",
+  "odotettiin '{0}':a, mutta luettiin '{1}'.",
   "'{0}' on redundantti.",
   "tupla voi esiintyä ainoastaan mallin viimeisenä parametrina.",
   "funktion alkuehto jäsennettiin jo.",
   "funktion loppuehto jäsennettiin jo.",
   "linkitystyyppiä ei määritelty.",
   "tunnistamaton linkitystyyppi '{0}'; sallittuja tyyppejä ovat C, C++, D, Windows, Pascal ja System.",
-  "expected one or more base classes, not '{0}'.", // TODO: translate
-  "base classes are not allowed in forward declarations.", // TODO: translate
+  "odotettiin yhtä tai useampaa luokkaa, ei '{0}':ta.",
+  "kantaluokat eivät ole sallittuja etukäteismäärittelyissä.",
 
   // Help messages:
   `dil v{0}
@@ -88,4 +88,4 @@
   dil gen Parser.d --html --syntax > Parser.html`,
 
   ``,
-];
\ No newline at end of file
+];