[monkeydoc] Rename to use proper casing
authorJérémie Laval <jeremie.laval@gmail.com>
Wed, 19 Dec 2012 11:09:13 +0000 (12:09 +0100)
committerJérémie Laval <jeremie.laval@gmail.com>
Wed, 19 Dec 2012 11:09:13 +0000 (12:09 +0100)
82 files changed:
mcs/tools/monkeydoc/MonkeyDoc.Ecma/EcmaDesc.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc.Ecma/EcmaUrlParser.jay [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc.Ecma/EcmaUrlParserDriver.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc.Ecma/EcmaUrlTokenizer.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/HelpSource.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/Node.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/Provider.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/RootTree.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/SearchableDocument.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/SearchableIndex.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/Tree.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/TypeUtils.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/cache.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/caches/FileCache.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/caches/NullCache.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/generator.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/generators/HtmlGenerator.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/generators/RawGenerator.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/generators/html/Addin2Html.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/generators/html/Ecma2Html.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/generators/html/Ecmaspec2Html.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/generators/html/Error2Html.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/generators/html/Idem.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/generators/html/Man2Html.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/generators/html/MonoBook2Html.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/generators/html/Toc2Html.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/index.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/providers/EcmaDoc.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/providers/addins-provider.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/providers/ecma-provider.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/providers/ecmaspec-provider.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/providers/ecmauncompiled-provider.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/providers/error-provider.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/providers/man-provider.cs [new file with mode: 0755]
mcs/tools/monkeydoc/MonkeyDoc/providers/simple-provider.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/providers/xhtml-provider.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/settings.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/storage.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/storage/NullStorage.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/storage/UncompiledDocStorage.cs [new file with mode: 0644]
mcs/tools/monkeydoc/MonkeyDoc/storage/ZipStorage.cs [new file with mode: 0644]
mcs/tools/monkeydoc/Monkeydoc.Ecma/EcmaDesc.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc.Ecma/EcmaUrlParser.jay [deleted file]
mcs/tools/monkeydoc/Monkeydoc.Ecma/EcmaUrlParserDriver.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc.Ecma/EcmaUrlTokenizer.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/HelpSource.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/Node.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/Provider.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/RootTree.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/SearchableDocument.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/SearchableIndex.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/Tree.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/TypeUtils.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/cache.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/caches/FileCache.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/caches/NullCache.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/generator.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/generators/HtmlGenerator.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/generators/RawGenerator.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/generators/html/Addin2Html.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/generators/html/Ecma2Html.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/generators/html/Ecmaspec2Html.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/generators/html/Error2Html.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/generators/html/Idem.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/generators/html/Man2Html.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/generators/html/MonoBook2Html.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/generators/html/Toc2Html.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/index.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/providers/EcmaDoc.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/providers/addins-provider.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/providers/ecma-provider.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/providers/ecmaspec-provider.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/providers/ecmauncompiled-provider.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/providers/error-provider.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/providers/man-provider.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/providers/simple-provider.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/providers/xhtml-provider.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/settings.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/storage.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/storage/NullStorage.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/storage/UncompiledDocStorage.cs [deleted file]
mcs/tools/monkeydoc/Monkeydoc/storage/ZipStorage.cs [deleted file]

diff --git a/mcs/tools/monkeydoc/MonkeyDoc.Ecma/EcmaDesc.cs b/mcs/tools/monkeydoc/MonkeyDoc.Ecma/EcmaDesc.cs
new file mode 100644 (file)
index 0000000..19c3ce4
--- /dev/null
@@ -0,0 +1,333 @@
+using System;
+using System.Linq;
+using System.Text;
+using System.Collections.Generic;
+
+namespace MonkeyDoc.Ecma
+{
+       /* Some properties might not be filled/meaningful depending on kind
+        * like a namespace EcmaUrl won't have a valid TypeName
+        */
+       public class EcmaDesc : IEquatable<EcmaDesc>
+       {
+               public enum Kind
+               {
+                       Type,
+                       Constructor,
+                       Method,
+                       Namespace,
+                       Field,
+                       Property,
+                       Event,
+                       Operator
+               }
+
+               public enum Mod
+               {
+                       Normal,
+                       Pointer,
+                       Ref,
+                       Out
+               }
+
+               public enum Format
+               {
+                       WithArgs,
+                       WithoutArgs
+               }
+
+               public Kind DescKind {
+                       get;
+                       set;
+               }
+
+               public Mod DescModifier {
+                       get;
+                       set;
+               }
+
+               public string Namespace {
+                       get;
+                       set;
+               }
+
+               public string TypeName {
+                       get;
+                       set;
+               }
+
+               public string MemberName {
+                       get;
+                       set;
+               }
+
+               public EcmaDesc NestedType {
+                       get;
+                       set;
+               }
+
+               /* A list of the array dimensions attached to this type.
+                * The list count corresponds to the number of recursive
+                * array definition (jagged arrays) the value of the
+                * corresponding list item is the number of dimension
+                * attached to that array definition instance
+                */
+               public IList<int> ArrayDimensions {
+                       get;
+                       set;
+               }
+
+               /* Depending on the form of the url, we might not have the type
+                * of the argument but only how many the type/member has i.e.
+                * when such number is specified with a backtick
+                */
+               public IList<EcmaDesc> GenericTypeArguments {
+                       get;
+                       set;
+               }
+
+               public IList<EcmaDesc> GenericMemberArguments {
+                       get;
+                       set;
+               }
+
+               public IList<EcmaDesc> MemberArguments {
+                       get;
+                       set;
+               }
+
+               /* This indicates that we actually want an inner part of the ecmadesc
+                * i.e. in case of T: we could want the members (*), ctor (C), methods (M), ...
+                */
+               public char Etc {
+                       get;
+                       set;
+               }
+
+               public bool IsEtc {
+                       get {
+                               return Etc != (char)0;
+                       }
+               }
+
+               /* EtcFilter is only valid in some case of IsEtc when the inner part needs
+                * to be further filtered e.g. in case we want a listing of the type overloads
+                * Equals
+                */
+               public string EtcFilter {
+                       get;
+                       set;
+               }
+
+               /* When a member is an explicit implementation of an interface member, we register
+                * the member EcmaDesc with its interface parent here
+                */
+               public EcmaDesc ExplicitImplMember {
+                       get;
+                       set;
+               }
+
+               // Returns the TypeName and the generic/inner type information if existing
+               public string ToCompleteTypeName (char innerTypeSeparator = '.')
+               {
+                       var result = TypeName;
+                       if (GenericTypeArguments != null)
+                               result += FormatGenericArgs (GenericTypeArguments);
+                       if (NestedType != null)
+                               result += innerTypeSeparator + NestedType.ToCompleteTypeName ();
+                       if (ArrayDimensions != null && ArrayDimensions.Count > 0)
+                               result += ArrayDimensions.Select (dim => "[" + new string (',', dim - 1) + "]").Aggregate (string.Concat);
+
+                       return result;
+               }
+
+               // Returns the member name with its generic types if existing
+               public string ToCompleteMemberName (Format format)
+               {
+                       /* We special process two cases:
+                        *   - Explicit member implementation which append a full type specification
+                        *   - Conversion operator which are exposed as normal method but have specific captioning in the end
+                        */
+                       if (ExplicitImplMember != null) {
+                               var impl = ExplicitImplMember;
+                               return impl.FormattedNamespace + impl.ToCompleteTypeName () + "." + impl.ToCompleteMemberName (format);
+                       } else if (format == Format.WithArgs && DescKind == Kind.Operator && MemberName.EndsWith ("Conversion")) {
+                               var type1 = MemberArguments[0].FormattedNamespace + MemberArguments[0].ToCompleteTypeName () + ModToString (MemberArguments[0]);
+                               var type2 = MemberArguments[1].FormattedNamespace + MemberArguments[1].ToCompleteTypeName () + ModToString (MemberArguments[1]);
+                               return type1 + " to " + type2;
+                       }
+
+                       var result = IsEtc && !string.IsNullOrEmpty (EtcFilter) ? EtcFilter : MemberName;
+
+                       // Temporary hack for monodoc produced inner type ctor
+                       //if (DescKind == Kind.Constructor && NestedType != null)
+                               //result = ToCompleteTypeName ();
+
+                       if (GenericMemberArguments != null)
+                               result += FormatGenericArgs (GenericMemberArguments);
+
+                       if (format == Format.WithArgs) {
+                               result += '(';
+                               if (MemberArguments != null && MemberArguments.Count > 0) {
+                                       var args = MemberArguments.Select (a => FormatNamespace (a) + a.ToCompleteTypeName ('+') + ModToString (a));
+                                       result += string.Join (",", args);
+                               }
+                               result += ')';
+                       }
+
+                       return result;
+               }
+
+               public string ToEcmaCref ()
+               {
+                       var sb = new StringBuilder ();
+                       // Cref type
+                       sb.Append (DescKind.ToString ()[0]);
+                       // Create the rest
+                       ConstructCRef (sb);
+
+                       return sb.ToString ();
+               }
+
+               void ConstructCRef (StringBuilder sb)
+               {
+                       sb.Append (Namespace);
+                       if (DescKind == Kind.Namespace)
+                               return;
+
+                       sb.Append ('.');
+                       sb.Append (TypeName);
+                       if (GenericTypeArguments != null) {
+                               sb.Append ('<');
+                               foreach (var t in GenericTypeArguments)
+                                       t.ConstructCRef (sb);
+                               sb.Append ('>');
+                       }
+                       if (NestedType != null) {
+                               sb.Append ('+');
+                               NestedType.ConstructCRef (sb);
+                       }
+                       if (ArrayDimensions != null && ArrayDimensions.Count > 0) {
+                               for (int i = 0; i < ArrayDimensions.Count; i++) {
+                                       sb.Append ('[');
+                                       sb.Append (new string (',', ArrayDimensions[i] - 1));
+                                       sb.Append (']');
+                               }
+                       }
+                       if (DescKind == Kind.Type)
+                               return;
+
+                       if (MemberArguments != null) {
+                               
+                       }
+               }
+
+               public override string ToString ()
+               {
+                       return string.Format ("({8}) {0}::{1}{2}{3}{7} {4}{5}{6} {9} {10}",
+                                             Namespace,
+                                             TypeName,
+                                             FormatGenericArgsFull (GenericTypeArguments),
+                                             NestedType != null ? "+" + NestedType.ToString () : string.Empty,
+                                             MemberName ?? string.Empty,
+                                             FormatGenericArgsFull (GenericMemberArguments),
+                                             MemberArguments != null ? "(" + string.Join (",", MemberArguments.Select (m => m.ToString ())) + ")" : string.Empty,
+                                             ArrayDimensions != null && ArrayDimensions.Count > 0 ? ArrayDimensions.Select (dim => "[" + new string (',', dim - 1) + "]").Aggregate (string.Concat) : string.Empty,
+                                             DescKind.ToString ()[0],
+                                             Etc != 0 ? '(' + Etc.ToString () + ')' : string.Empty,
+                                             ExplicitImplMember != null ? "$" + ExplicitImplMember.ToString () : string.Empty);
+                                             
+               }
+
+               public override bool Equals (object other)
+               {
+                       var otherDesc = other as EcmaDesc;
+                       return otherDesc != null && Equals (otherDesc);
+               }
+
+               public bool Equals (EcmaDesc other)
+               {
+                       if (other == null)
+                               return false;
+
+                       if (NestedType == null ^ other.NestedType == null
+                           || ArrayDimensions == null ^ other.ArrayDimensions == null
+                           || GenericTypeArguments == null ^ other.GenericTypeArguments == null
+                           || GenericMemberArguments == null ^ other.GenericMemberArguments == null
+                           || MemberArguments == null ^ other.MemberArguments == null
+                           || ExplicitImplMember == null ^ other.ExplicitImplMember == null)
+                               return false;
+
+                       return other != null
+                               && DescKind == other.DescKind
+                               && TypeName == other.TypeName
+                               && Namespace == other.Namespace
+                               && MemberName == other.MemberName
+                               && (NestedType == null || NestedType.Equals (other.NestedType))
+                               && (ArrayDimensions == null || ArrayDimensions.SequenceEqual (other.ArrayDimensions))
+                               && (GenericTypeArguments == null || GenericTypeArguments.SequenceEqual (other.GenericTypeArguments))
+                               && (GenericMemberArguments == null || GenericMemberArguments.SequenceEqual (other.GenericMemberArguments))
+                               && (MemberArguments == null || MemberArguments.SequenceEqual (other.MemberArguments))
+                               && Etc == other.Etc
+                               && EtcFilter == other.EtcFilter
+                               && (ExplicitImplMember == null || ExplicitImplMember.Equals (other.ExplicitImplMember));
+               }
+
+               public override int GetHashCode ()
+               {
+                       return DescKind.GetHashCode ()
+                               ^ TypeName.GetHashCode ()
+                               ^ Namespace.GetHashCode ()
+                               ^ MemberName.GetHashCode ();
+               }
+
+               bool What (bool input)
+               {
+                       if (!input)
+                               throw new Exception ("Not equal");
+                       return input;
+               }
+
+               bool WhatT (bool input)
+               {
+                       if (input)
+                               throw new Exception ("Not equal");
+                       return input;
+               }
+
+               string FormatNamespace (EcmaDesc desc)
+               {
+                       return string.IsNullOrEmpty (desc.Namespace) ? string.Empty : desc.Namespace + ".";
+               }
+
+               string FormatGenericArgs (IEnumerable<EcmaDesc> genericArgs)
+               {
+                       return genericArgs != null ? "<" + string.Join (",", genericArgs.Select (t => FormatNamespace (t) + t.ToCompleteTypeName ())) + ">" : string.Empty;
+               }
+
+               string FormatGenericArgsFull (IEnumerable<EcmaDesc> genericArgs)
+               {
+                       return genericArgs != null ? "<" + string.Join (",", genericArgs.Select (t => t.ToString ())) + ">" : string.Empty;
+               }
+
+               string ModToString (EcmaDesc desc)
+               {
+                       switch (desc.DescModifier) {
+                       case Mod.Pointer:
+                               return "*";
+                       case Mod.Ref:
+                               return "&";
+                       case Mod.Out:
+                               return "@";
+                       default:
+                               return string.Empty;
+                       }
+               }
+
+               string FormattedNamespace {
+                       get {
+                               return !string.IsNullOrEmpty (Namespace) ? Namespace + "." : string.Empty;
+                       }
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/MonkeyDoc.Ecma/EcmaUrlParser.jay b/mcs/tools/monkeydoc/MonkeyDoc.Ecma/EcmaUrlParser.jay
new file mode 100644 (file)
index 0000000..e136bc2
--- /dev/null
@@ -0,0 +1,263 @@
+%{
+using System.Text;
+using System.IO;
+using System;
+using System.Linq;
+using System.Collections.Generic;
+
+namespace MonkeyDoc.Ecma
+{
+       public class EcmaUrlParser
+       {
+        int yacc_verbose_flag = 0;
+
+        public void IsValid (string input)
+        {
+                       var lexer = new EcmaUrlTokenizer (input);
+                       this.yyparse (lexer);
+        }
+
+        public EcmaDesc Parse (string input)
+        {
+                       var lexer = new EcmaUrlTokenizer (input);
+                       return (EcmaDesc)this.yyparse (lexer);
+        }
+
+        public bool TryParse (string input, out EcmaDesc desc)
+        {
+            desc = null;
+            try {
+                desc = Parse (input);
+            } catch {
+                return false;
+            }
+            return true;
+        }
+
+        EcmaDesc SetEcmaDescType (object result, EcmaDesc.Kind kind)
+        {
+            var desc = result as EcmaDesc;
+            desc.DescKind = kind;
+            return desc;
+        }
+
+        List<T> SafeReverse<T> (List<T> input)
+        {
+            if (input == null)
+               return null;
+            input.Reverse ();
+            return input;
+        }
+%}
+
+%token ERROR
+%token IDENTIFIER
+%token DIGIT
+%token DOT
+%token COMMA
+%token COLON
+%token INNER_TYPE_SEPARATOR
+%token OP_GENERICS_LT
+%token OP_GENERICS_GT
+%token OP_GENERICS_BACKTICK
+%token OP_OPEN_PAREN
+%token OP_CLOSE_PAREN
+%token OP_ARRAY_OPEN
+%token OP_ARRAY_CLOSE
+%token SLASH_SEPARATOR
+%token STAR
+%token REF_ARG
+%token OUT_ARG
+%token EXPLICIT_IMPL_SEP
+
+%start expression
+
+%%
+
+expression
+        : 'T' COLON type_expression { $$ = SetEcmaDescType ($3, EcmaDesc.Kind.Type); }
+        | 'N' COLON namespace_expression { $$ = SetEcmaDescType ($3, EcmaDesc.Kind.Namespace); }
+        | 'M' COLON method_expression { $$ = SetEcmaDescType ($3, EcmaDesc.Kind.Method); }
+        | 'F' COLON simple_member_expression { $$ = SetEcmaDescType ($3, EcmaDesc.Kind.Field); }
+        | 'C' COLON constructor_expression { $$ = SetEcmaDescType ($3, EcmaDesc.Kind.Constructor); }
+        | 'P' COLON property_expression { $$ = SetEcmaDescType ($3, EcmaDesc.Kind.Property); }
+        | 'E' COLON simple_member_expression { $$ = SetEcmaDescType ($3, EcmaDesc.Kind.Event); }
+        | 'O' COLON operator_expression { $$ = SetEcmaDescType ($3, EcmaDesc.Kind.Operator); }
+
+/* i.e. id.id.id or id */
+dot_expression
+        : IDENTIFIER { $$ = new List<string> { (string)$1 }; }
+        | IDENTIFIER DOT dot_expression { ((ICollection<string>)$3).Add ((string)$1); $$ = $3; }
+
+namespace_expression
+        : dot_expression { $$ = new EcmaDesc { Namespace = string.Join (".", ((IEnumerable<string>)$1).Reverse ()) }; }
+
+type_expression
+        : dot_expression type_expression_suffix {
+                         var dotExpr = ((List<string>)$1);
+                         dotExpr.Reverse ();
+                         var desc = $2 as EcmaDesc;
+                         desc.DescKind = EcmaDesc.Kind.Type;
+                         desc.Namespace = string.Join (".", dotExpr.Take (dotExpr.Count - 1));
+                         desc.TypeName = dotExpr.Last ();
+                         $$ = desc;
+                     }
+
+/* To be used in types with no namespaces attached to them like an inner type*/
+reduced_type_expression
+        : IDENTIFIER type_expression_suffix {
+                         var desc = $2 as EcmaDesc;
+                         desc.DescKind = EcmaDesc.Kind.Type;
+                         desc.TypeName = $1 as string;
+                         $$ = desc;
+                     }
+
+type_expression_suffix
+        : opt_generic_type_suffix opt_inner_type_description opt_array_definition opt_etc {
+                         bool nestedDescHasEtc = $2 != null && ((EcmaDesc)$2).IsEtc;
+                         EcmaDesc nestedType = (EcmaDesc)$2;
+                         $$ = new EcmaDesc {
+                            GenericTypeArguments = $1 as List<EcmaDesc>,
+                            NestedType = nestedType,
+                            ArrayDimensions = SafeReverse ($3 as List<int>),
+                            Etc = $4 != null ? ((Tuple<char, string>)$4).Item1 : nestedDescHasEtc ? nestedType.Etc : (char)0,
+                            EtcFilter = $4 != null ? ((Tuple<char, string>)$4).Item2 : nestedDescHasEtc ? nestedType.EtcFilter : null
+                         };
+                         if (nestedDescHasEtc) {
+                            nestedType.Etc = (char)0;
+                            nestedType.EtcFilter = null;
+                         }
+                     }
+
+opt_inner_type_description
+        : /* empty */ { $$ = null; }
+        | INNER_TYPE_SEPARATOR reduced_type_expression { $$ = $2; }
+
+opt_generic_type_suffix
+        : /* empty */ { $$ = null; }
+        | OP_GENERICS_BACKTICK DIGIT { $$ = Enumerable.Repeat<string> (null, (int)$2).ToList (); }
+        | OP_GENERICS_LT generic_type_arg_list OP_GENERICS_GT { $$ = $2; }
+
+generic_type_arg_list
+        : type_expression { $$ = new List<EcmaDesc> () { (EcmaDesc)$1 }; }
+        | generic_type_arg_list COMMA type_expression { ((List<EcmaDesc>)$1).Add ((EcmaDesc)$3); $$ = $1; }
+
+opt_array_definition
+        : /* empty */ { $$ = null; }
+        | OP_ARRAY_OPEN opt_array_definition_list OP_ARRAY_CLOSE opt_array_definition {
+                      var dims = ((IList<int>)$4) ?? new List<int> (2);
+                      dims.Add ((int)$2);
+                      $$ = dims;
+                }
+
+opt_array_definition_list
+        : /* empty */ { $$ = 1; }
+        | COMMA opt_array_definition_list { $$ = ((int)$2) + 1; }
+
+opt_etc
+        : /* empty */ { $$ = null; }
+        | SLASH_SEPARATOR etc_identifier { $$ = Tuple.Create<char, string> (((string)$2)[0], null); }
+        | SLASH_SEPARATOR etc_identifier SLASH_SEPARATOR reduced_member_expression { $$ = Tuple.Create<char, string> (((string)$2)[0], (string)$4); }
+/*        | SLASH_SEPARATOR etc_identifier SLASH_SEPARATOR IDENTIFIER opt_generic_type_suffix { $$ = Tuple.Create<char, string> (((string)$2)[0], (string)$4 + ($5 == null ? string.Empty : "<" + string.Join (",", ((IEnumerable<EcmaDesc>)$5).Select (t => t.ToCompleteTypeName ())) + ">")); } */
+
+etc_identifier
+        : STAR { $$ = "*"; }
+        | IDENTIFIER { $$ = $1; }
+
+method_expression
+        : type_expression DOT IDENTIFIER opt_generic_type_suffix opt_arg_list_suffix {
+                      var desc = $1 as EcmaDesc;
+                      desc.MemberName = $3 as string;
+                      desc.GenericMemberArguments = $4 as List<EcmaDesc>;
+                      desc.MemberArguments = SafeReverse ($5 as List<EcmaDesc>);
+                      $$ = desc;
+                }
+        | dot_expression opt_generic_type_suffix opt_arg_list_suffix {
+                      var dotExpr = ((List<string>)$1);
+                      $$ = new EcmaDesc {
+                           Namespace = string.Join (".", dotExpr.Skip (2).DefaultIfEmpty (string.Empty).Reverse ()),
+                           TypeName = dotExpr.Skip (1).First (),
+                           MemberName = dotExpr.First (),
+                           GenericMemberArguments = $2 as List<EcmaDesc>,
+                           MemberArguments = SafeReverse ($3 as List<EcmaDesc>)
+                      };
+                }
+        | type_expression EXPLICIT_IMPL_SEP method_expression {
+                      var desc = $1 as EcmaDesc;
+                      desc.ExplicitImplMember = $3 as EcmaDesc;
+                      $$ = desc;
+                }
+
+/* To be used with members that may have no type/namespace attached */
+reduced_member_expression
+        : IDENTIFIER opt_generic_type_suffix { $$ = (string)$1 + ($2 == null ? string.Empty : "<" + string.Join (",", ((IEnumerable<EcmaDesc>)$2).Select (t => t.ToCompleteTypeName ())) + ">"); }
+        | IDENTIFIER opt_generic_type_suffix DOT reduced_member_expression {
+                      var existing = $4 as string;
+                      var expr = (string)$1 + ($2 == null ? string.Empty : "<" + string.Join (",", ((IEnumerable<EcmaDesc>)$2).Select (t => t.ToCompleteTypeName ())) + ">");
+                      $$ = expr + "." + existing;
+                }
+
+arg_type_expression
+        : type_expression opt_arg_type_suffix { var desc = (EcmaDesc)$1; desc.DescModifier = (EcmaDesc.Mod)$2; $$ = desc; }
+
+opt_arg_type_suffix
+        : /* empty */ { $$ = EcmaDesc.Mod.Normal; }
+        | STAR { $$ = EcmaDesc.Mod.Pointer; }
+        | REF_ARG { $$ = EcmaDesc.Mod.Ref; }
+        | OUT_ARG { $$ = EcmaDesc.Mod.Out; }
+
+type_expression_list
+        : /* empty */ { $$ = null; }
+        | arg_type_expression { $$ = new List<EcmaDesc> () { (EcmaDesc)$1 }; }
+        | arg_type_expression COMMA type_expression_list { ((List<EcmaDesc>)$3).Add ((EcmaDesc)$1); $$ = $3; }
+
+simple_member_expression
+        : dot_expression {
+                 var dotExpr = ((List<string>)$1);
+                 dotExpr.Reverse ();
+
+                 $$ = new EcmaDesc {
+                      Namespace = dotExpr.Count > 2 ? string.Join (".", dotExpr.Take (dotExpr.Count - 2)) : string.Empty,
+                      TypeName = dotExpr.Count > 1 ?  dotExpr[dotExpr.Count - 2] : string.Empty,
+                      MemberName = dotExpr[dotExpr.Count - 1]
+                 };
+             }
+        | type_expression DOT IDENTIFIER {
+                 var desc = $1 as EcmaDesc;
+                 desc.MemberName = $3 as string;
+                 $$ = desc;
+             }
+        | type_expression EXPLICIT_IMPL_SEP simple_member_expression {
+                 var desc = $1 as EcmaDesc;
+                 desc.ExplicitImplMember = $3 as EcmaDesc;
+                 $$ = desc;
+             }
+
+constructor_expression
+        : method_expression { $$ = $1; }
+
+operator_expression
+        : method_expression { $$ = $1; }
+
+property_expression
+        : simple_member_expression opt_property_indexer {
+                 var desc = $1 as EcmaDesc;
+                 (desc.ExplicitImplMember ?? desc).MemberArguments = SafeReverse ($2 as List<EcmaDesc>);
+                 $$ = desc;
+             }
+
+opt_property_indexer
+        : opt_arg_list_suffix { $$ = $1; }
+
+/*simple_member_expression opt_arg_list_suffix { $$ = CopyFromEcmaDesc (new EcmaDesc {
+                           MemberArguments = SafeReverse ($2 as List<EcmaDesc>)
+                      }, (EcmaDesc)$1);
+                }*/
+
+opt_arg_list_suffix
+        : /* empty */ { $$ = null; }
+        | OP_OPEN_PAREN type_expression_list OP_CLOSE_PAREN { $$ = $2; }
+
+%%
+
+}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/MonkeyDoc.Ecma/EcmaUrlParserDriver.cs b/mcs/tools/monkeydoc/MonkeyDoc.Ecma/EcmaUrlParserDriver.cs
new file mode 100644 (file)
index 0000000..af3978f
--- /dev/null
@@ -0,0 +1,17 @@
+using System;
+using System.IO;
+
+namespace MonkeyDoc.Ecma
+{
+       public class EcmaUrlParserDriver
+       {
+               public static void Main (string[] args)
+               {
+                       var input = new StringReader (args[0]);
+                       var lexer = new EcmaUrlTokenizer (input);
+                       var parser = new EcmaUrlParser ();
+
+                       Console.WriteLine (parser.yyparse (lexer));
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/MonkeyDoc.Ecma/EcmaUrlTokenizer.cs b/mcs/tools/monkeydoc/MonkeyDoc.Ecma/EcmaUrlTokenizer.cs
new file mode 100644 (file)
index 0000000..91bf6db
--- /dev/null
@@ -0,0 +1,168 @@
+using System;
+using System.Text;
+using System.Globalization;
+
+namespace MonkeyDoc.Ecma
+{
+       public class EcmaUrlTokenizer : yyParser.yyInput
+       {
+               const char EndOfStream = (char)0;
+               string input;
+               object val;
+               int current_token;
+               int current_pos;
+               int real_current_pos;
+               int identCount = 0;
+
+               public EcmaUrlTokenizer (string input)
+               {
+                       this.input = input;
+               }
+
+               static bool is_identifier_start_character (char c)
+               {
+                       return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || Char.IsLetter (c);
+               }
+
+               static bool is_identifier_part_character (char c)
+               {
+                       if (c >= 'a' && c <= 'z')
+                               return true;
+
+                       if (c >= 'A' && c <= 'Z')
+                               return true;
+
+                       if (c == '_' || (c >= '0' && c <= '9'))
+                               return true;
+
+                       if (c < 0x80)
+                               return false;
+
+                       return Char.IsLetter (c) || Char.GetUnicodeCategory (c) == UnicodeCategory.ConnectorPunctuation;
+               }
+
+               public bool advance ()
+               {
+                       return Peek () != EndOfStream;
+               }
+
+               public Object Value {
+                       get {
+                               return val;
+                       }
+               }
+
+               public Object value ()
+               {
+                       return val;
+               }
+
+               public int token ()
+               {
+                       int token = xtoken ();
+                       //Console.WriteLine ("Current token {0} with value {1}", token, val == null ? "(none)" : val.ToString ());
+                       if (token == Token.ERROR)
+                               Console.WriteLine ("Problem at pos {0} after token {1}", current_pos, current_token);
+                       current_token = token;
+                       return token;
+               }
+
+               int xtoken ()
+               {
+                       char next = Read ();
+                       while (char.IsWhiteSpace (next))
+                               next = Read ();
+                       current_pos++;
+                       val = null;
+
+                       switch (next) {
+                       case ',':
+                               return Token.COMMA;
+                       case '.':
+                               return Token.DOT;
+                       case '<':
+                               return Token.OP_GENERICS_LT;
+                       case '>':
+                               return Token.OP_GENERICS_GT;
+                       case '`':
+                               return Token.OP_GENERICS_BACKTICK;
+                       case '(':
+                               return Token.OP_OPEN_PAREN;
+                       case ')':
+                               return Token.OP_CLOSE_PAREN;
+                       case '+':
+                               return Token.INNER_TYPE_SEPARATOR;
+                       case ':':
+                               return Token.COLON;
+                       case '/':
+                               return Token.SLASH_SEPARATOR;
+                       case '[':
+                               return Token.OP_ARRAY_OPEN;
+                       case ']':
+                               return Token.OP_ARRAY_CLOSE;
+                       case '*':
+                               return Token.STAR;
+                       case '&':
+                               return Token.REF_ARG;
+                       case '@':
+                               return Token.OUT_ARG;
+                       case '$':
+                               return Token.EXPLICIT_IMPL_SEP;
+                       default:
+                               return TokenizeIdentifierOrNumber (next);
+                       }
+               }
+
+               int TokenizeIdentifierOrNumber (char current)
+               {
+                       // We must first return the expression type which is a uppercase letter and a colon
+                       if (current_pos < 2) {
+                               val = null;
+                               return (int)current;
+                       }
+
+                       if (is_identifier_start_character (current) || current == '*') {
+                               unsafe {
+                                       // identifier length is artificially limited to 1024 bytes by implementations
+                                       char* pIdent = stackalloc char[512];
+                                       *pIdent = current;
+                                       identCount = 1;
+
+                                       char peek;
+                                       while ((peek = Peek ()) != EndOfStream && is_identifier_part_character (peek)) {
+                                               *(pIdent + identCount) = Read ();
+                                               ++current_pos;
+                                               ++identCount;
+                                       }
+
+                                       val = new string ((char*)pIdent, 0, identCount);
+                                       return Token.IDENTIFIER;
+                               }
+                       } else if (char.IsDigit (current)) {
+                               val = current - '0';
+                               return Token.DIGIT;
+                       } else {
+                               val = null;
+                               return Token.ERROR;
+                       }
+               }
+
+               char Read ()
+               {
+                       try {
+                               return input[real_current_pos++];
+                       } catch {
+                               return EndOfStream;
+                       }
+               }
+
+               char Peek ()
+               {
+                       try {
+                               return input[real_current_pos];
+                       } catch {
+                               return EndOfStream;
+                       }
+               }
+       }
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/HelpSource.cs b/mcs/tools/monkeydoc/MonkeyDoc/HelpSource.cs
new file mode 100644 (file)
index 0000000..14cf446
--- /dev/null
@@ -0,0 +1,339 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using System.Diagnostics;
+using System.Collections.Generic;
+
+using Mono.Utilities;
+using Lucene.Net.Index;
+
+namespace MonkeyDoc
+{
+       //
+       // The HelpSource class keeps track of the archived data, and its
+       // tree
+       //
+       public class HelpSource
+       {
+               static int id;
+
+               //
+               // The unique ID for this HelpSource.
+               //
+               int source_id;
+
+               // The name of the HelpSource, used by all the file (.tree, .zip, ...) used by it
+               string name;
+               // The full directory path where the HelpSource files are located
+               string basePath;
+
+               // The tree of this help source
+               Tree tree;
+               string treeFilePath;
+               RootTree rootTree;
+
+               IDocCache cache;
+               IDocStorage storage;
+
+               public HelpSource (string base_filename, bool create)
+               {
+                       this.name = Path.GetFileName (base_filename);
+                       this.basePath = Path.GetDirectoryName (base_filename);
+                       this.treeFilePath = base_filename + ".tree";
+                       this.storage = new MonkeyDoc.Storage.ZipStorage (base_filename + ".zip");
+                       this.cache = DocCacheHelper.GetDefaultCache (Name);
+
+                       tree = create ? new Tree (this, string.Empty, string.Empty) : new Tree (this, treeFilePath);
+
+                       source_id = id++;
+               }
+       
+               public HelpSource ()
+               {
+                       tree = new Tree (this, "Blah", "Blah");
+                       source_id = id++;
+               }
+       
+               public int SourceID {
+                       get {
+                               return source_id;
+                       }
+               }
+       
+               public string Name {
+                       get {
+                               return name;
+                       }
+               }
+
+               /* This gives the full path of the source/ directory */
+               public string BaseFilePath {
+                       get {
+                               return basePath;
+                       }
+               }
+
+               public TraceLevel TraceLevel {
+                       get;
+                       set;
+               }
+
+               public string BaseDir {
+                       get {
+                               return basePath;
+                       }
+               }
+
+               public Tree Tree {
+                       get {
+                               return tree;
+                       }
+               }
+
+               public RootTree RootTree {
+                       get {
+                               return rootTree;
+                       }
+                       set {
+                               rootTree = value;
+                       }
+               }
+
+               public IDocCache Cache {
+                       get {
+                               return cache;
+                       }
+               }
+
+               public IDocStorage Storage {
+                       get {
+                               return storage;
+                       }
+                       protected set {
+                               storage = value;
+                       }
+               }
+
+               // A HelpSource may have a common prefix to its URL, give it here
+               protected virtual string UriPrefix {
+                       get {
+                               return "dummy:";
+                       }
+               }
+       
+               /// <summary>
+               ///   Returns a stream from the packaged help source archive
+               /// </summary>
+               public virtual Stream GetHelpStream (string id)
+               {
+                       return storage.Retrieve (id);
+               }
+
+               public virtual Stream GetCachedHelpStream (string id)
+               {
+                       if (string.IsNullOrEmpty (id))
+                               throw new ArgumentNullException ("id");
+                       if (!cache.CanCache (DocEntity.Text))
+                               return GetHelpStream (id);
+                       if (!cache.IsCached (id))
+                               cache.CacheText (id, GetHelpStream (id));
+                       return cache.GetCachedStream (id);
+               }
+
+               public XmlReader GetHelpXml (string id)
+               {
+                       var url = "monodoc:///" + SourceID + "@" + Uri.EscapeDataString (id) + "@";
+                       var stream = cache.IsCached (id) ? cache.GetCachedStream (id) : storage.Retrieve (id);
+                       
+                       return stream == null ? null : new XmlTextReader (url, stream);
+               }
+       
+               public virtual XmlDocument GetHelpXmlWithChanges (string id)
+               {
+                       XmlDocument doc = new XmlDocument ();
+                       if (!storage.SupportRevision) {
+                               doc.Load (GetHelpXml (id));
+                       } else {
+                               var revManager = storage.RevisionManager;
+                               doc.Load (revManager.RetrieveLatestRevision (id));
+                       }
+                       return doc;
+               }
+
+               public virtual string GetCachedText (string id)
+               {
+                       if (!cache.CanCache (DocEntity.Text))
+                               return GetText (id);
+                       if (!cache.IsCached (id))
+                               cache.CacheText (id, GetText (id));
+                       return cache.GetCachedString (id);
+               }
+
+               public virtual string GetText (string id)
+               {
+                       return new StreamReader (GetHelpStream (id)).ReadToEnd ();
+               }
+
+               // Tells if the result for the provided id is generated dynamically
+               // by the help source
+               public virtual bool IsGeneratedContent (string id)
+               {
+                       return false;
+               }
+
+               // Tells if the content of the provided id is meant to be returned raw
+               public virtual bool IsRawContent (string id)
+               {
+                       return false;
+               }
+
+               // Tells if provided id refers to a multi-content-type document if it's case
+               // tells the ids it's formed of
+               public virtual bool IsMultiPart (string id, out IEnumerable<string> parts)
+               {
+                       parts = null;
+                       return false;
+               }
+
+               /// <summary>
+               ///   Saves the tree and the archive
+               /// </summary>
+               public void Save ()
+               {
+                       tree.Save (treeFilePath);
+                       storage.Dispose ();
+               }
+       
+               public virtual void RenderPreviewDocs (XmlNode newNode, XmlWriter writer)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public virtual string GetPublicUrl (Node node)
+               {
+                       return node.GetInternalUrl ();
+               }
+
+               public virtual bool CanHandleUrl (string url)
+               {
+                       return url.StartsWith (UriPrefix, StringComparison.OrdinalIgnoreCase);
+               }
+
+               public virtual string GetInternalIdForUrl (string url, out Node node)
+               {
+                       node = MatchNode (url);
+                       return node == null ? null : url.Substring (UriPrefix.Length);
+               }
+               
+               public virtual Node MatchNode (string url)
+               {
+                       Node current = null;
+
+                       var matchCache = LRUCache<string, Node>.Default;
+                       if ((current = matchCache.Get (url)) != null)
+                               return current;
+
+                       current = Tree.RootNode;
+                       var strippedUrl = url.StartsWith (UriPrefix, StringComparison.OrdinalIgnoreCase) ? url.Substring (UriPrefix.Length) : url;
+                       var searchNode = new Node () { Element = strippedUrl };
+
+                       do {
+                               int index = current.Nodes.BinarySearch (searchNode, NodeElementComparer.Instance);
+                               if (index >= 0) {
+                                       Node n = current.Nodes[index];
+                                       //Console.WriteLine ("Binarysearch success for {0} which fell on {1}", strippedUrl, n.Element);
+                                       matchCache.Put (url, n);
+                                       return n;
+                               }
+                               index = ~index;
+                               if (index == current.Nodes.Count) {
+                                       //Console.WriteLine ("Match fail for {0}", strippedUrl);
+                                       //Console.WriteLine (current.Nodes.Select (n => n.Element).Aggregate ((e1, e2) => e1 + ", " + e2));
+                                       return SlowMatchNode (Tree.RootNode, matchCache, strippedUrl);
+                               }
+                               current = current.Nodes [index - 1];
+                               //Console.WriteLine ("Binarysearch failed for {0}, next node check is {1}", strippedUrl, current.Element);
+                       } while (true);
+
+                       return null;
+               }
+
+               /* That slow path is mainly here to handle ecmaspec type of url which are composed of hard to sort numbers
+                * because they don't have the same amount of digit. We could use a regex to harmonise the various number
+                * parts but then it would be quite specific. Since in the case of ecmaspec the tree is well-formed enough
+                * the "Slow" match should still be fast enough
+                */
+               Node SlowMatchNode (Node current, LRUCache<string, Node> matchCache, string url)
+               {
+                       //Console.WriteLine ("Entering slow path for {0} starting from {1}", url, current.Element);
+                       while (current != null) {
+                               bool stop = true;
+                               foreach (Node n in current.Nodes) {
+                                       var element = n.Element.StartsWith (UriPrefix, StringComparison.OrdinalIgnoreCase) ? n.Element.Substring (UriPrefix.Length) : n.Element;
+                                       if (url == element) {
+                                               matchCache.Put (url, n);
+                                               return n;
+                                       } else if (url.StartsWith (element + ".", StringComparison.OrdinalIgnoreCase) && !n.IsLeaf) {
+                                               current = n;
+                                               stop = false;
+                                               break;
+                                       }
+                               }
+                               if (stop)
+                                       current = null;
+                       }
+
+                       return null;
+               }
+               
+               class NodeElementComparer : IComparer<Node>
+               {
+                       public static NodeElementComparer Instance = new NodeElementComparer ();
+
+                       public int Compare (Node n1, Node n2)
+                       {
+                               return string.Compare (Cleanup (n1), Cleanup (n2), StringComparison.Ordinal);
+                       }
+
+                       string Cleanup (Node n)
+                       {
+                               var prefix = n.Tree != null && n.Tree.HelpSource != null ? n.Tree.HelpSource.UriPrefix : string.Empty;
+                               var element = n.Element.StartsWith (prefix, StringComparison.OrdinalIgnoreCase) ? n.Element.Substring (prefix.Length) : n.Element;
+                               if (char.IsDigit (element, 0)) {
+                                       var count = element.TakeWhile (char.IsDigit).Count ();
+                                       element = element.PadLeft (Math.Max (0, 3 - count) + element.Length, '0');
+                               }
+                               //Console.WriteLine ("Cleaned up {0} to {1}", n.Element, element);
+                               return element;
+                       }
+               }
+
+               public virtual DocumentType GetDocumentTypeForId (string id, out Dictionary<string, string> extraParams)
+               {
+                       extraParams = null;
+                       return DocumentType.PlainText;
+               }
+
+               public virtual Stream GetImage (string url)
+               {
+                       return null;
+               }
+
+               //
+               // Populates the index.
+               //
+               public virtual void PopulateIndex (IndexMaker index_maker)
+               {
+               }
+
+               //
+               // Create different Documents for adding to Lucene search index
+               // The default action is do nothing. Subclasses should add the docs
+               // 
+               public virtual void PopulateSearchableIndex (IndexWriter writer)
+               {
+
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/Node.cs b/mcs/tools/monkeydoc/MonkeyDoc/Node.cs
new file mode 100644 (file)
index 0000000..8d9bd1e
--- /dev/null
@@ -0,0 +1,323 @@
+using System;
+using System.IO;
+using System.Text;
+using System.Linq;
+using System.Xml;
+using System.Collections.Generic;
+
+namespace MonkeyDoc
+{
+       public class Node : IComparable<Node>, IComparable
+       {
+               readonly Tree tree;
+               string caption, element, pubUrl;
+               public bool Documented;
+               bool loaded;
+               Node parent;
+               List<Node> nodes;
+               Dictionary<string, Node> childrenLookup;
+               /* Address has three types of value, 
+                *   _ 0 is for no on-disk representation
+                *   _ >0 is a valid address that is loaded immediately
+                *   _ <0 is a valid negated address to indicate lazy loading
+                */
+               int address;
+
+               public Node (Node parent, string caption, string element) : this (parent.Tree, caption, element)
+               {
+                       this.parent = parent;
+               }
+
+               internal Node (Tree tree, string caption, string element)
+               {
+                       this.tree = tree;
+                       this.caption = caption;
+                       this.element = element;
+               }
+       
+               /// <summary>
+               ///    Creates a node from an on-disk representation
+               /// </summary>
+               internal Node (Node parent, int address) : this (parent.tree, address)
+               {
+                       this.parent = parent;
+               }
+
+               internal Node (Tree tree, int address)
+               {
+                       this.address = address;
+                       this.tree = tree;
+                       if (address > 0)
+                               LoadNode ();
+               }
+
+               /* This is solely used for MatchNode to check for equality */
+               internal Node ()
+               {
+               }
+
+               void LoadNode ()
+               {
+                       tree.InflateNode (this);
+                       if (parent != null)
+                               parent.RegisterFullNode (this);
+               }
+
+               public void AddNode (Node n)
+               {
+                       nodes.Add (n);
+                       n.parent = this;
+                       n.Documented = true;
+                       RegisterFullNode (n);
+               }
+
+               public void DeleteNode (Node n)
+               {
+                       nodes.Remove (n);
+                       if (!string.IsNullOrEmpty (n.element))
+                               childrenLookup.Remove (n.element);
+               }
+
+               // When a child node is inflated, it calls this method
+               // so that we can add it to our lookup for quick search
+               void RegisterFullNode (Node child)
+               {
+                       if (childrenLookup == null)
+                               childrenLookup = new Dictionary<string, Node> ();
+                       if (!string.IsNullOrEmpty (child.element))
+                               childrenLookup[child.element] = child;
+               }
+
+               public List<Node> Nodes {
+                       get {
+                               EnsureLoaded ();
+                               return nodes != null ? nodes : new List<Node> ();
+                       }
+               }
+
+               public string Element {
+                       get {
+                               EnsureLoaded ();
+                               return element;
+                       }
+                       set {
+                               element = value;
+                       }
+               }
+
+               public string Caption {
+                       get {
+                               EnsureLoaded ();
+                               return caption;
+                       }
+                       internal set {
+                               caption = value;
+                       }
+               }
+       
+               public Node Parent {
+                       get {
+                               return parent;
+                       }
+               }
+
+               public Tree Tree {
+                       get {
+                               return tree;
+                       }
+               }
+
+               internal int Address {
+                       get {
+                               return address;
+                       }
+               }
+       
+               /// <summary>
+               ///   Creates a new node, in the locator entry point, and with
+               ///   a user visible caption of @caption
+               /// </summary>
+               public Node CreateNode (string c_caption, string c_element)
+               {
+                       EnsureNodes ();
+                       if (string.IsNullOrEmpty (c_caption))
+                               throw new ArgumentNullException ("c_caption");
+                       if (string.IsNullOrEmpty (c_element))
+                               throw new ArgumentNullException ("c_element");
+
+                       Node t = new Node (this, c_caption, c_element);
+                       nodes.Add (t);
+                       childrenLookup[c_element] = t;
+
+                       return t;
+               }
+
+               public Node GetOrCreateNode (string c_caption, string c_element)
+               {
+                       if (nodes == null)
+                               return CreateNode (c_caption, c_element);
+                       if (childrenLookup.Count != nodes.Count || (nodes.Count == 0 && childrenLookup.Count != nodes.Capacity))
+                               UpdateLookup ();
+
+                       Node result;
+                       if (!childrenLookup.TryGetValue (c_element, out result))
+                               result = CreateNode (c_caption, c_element);
+                       return result;
+               }
+
+               public void EnsureNodes ()
+               {
+                       if (nodes == null) {
+                               nodes = new List<Node> ();
+                               childrenLookup = new Dictionary<string, Node> ();
+                       }
+               }
+
+               public void EnsureLoaded ()
+               {
+                       if (address < 0 && !loaded) {
+                               LoadNode ();
+                               loaded = true;
+                       }
+               }
+
+               void UpdateLookup ()
+               {
+                       foreach (var node in nodes)
+                               childrenLookup[node.Element] = node;
+               }
+       
+               public bool IsLeaf {
+                       get {
+                               return nodes == null || nodes.Count == 0;
+                       }
+               }
+
+               void EncodeInt (BinaryWriter writer, int value)
+               {
+                       do {
+                               int high = (value >> 7) & 0x01ffffff;
+                               byte b = (byte)(value & 0x7f);
+
+                               if (high != 0) {
+                                       b = (byte)(b | 0x80);
+                               }
+                       
+                               writer.Write(b);
+                               value = high;
+                       } while(value != 0);
+               }
+
+               int DecodeInt (BinaryReader reader)
+               {
+                       int ret = 0;
+                       int shift = 0;
+                       byte b;
+               
+                       do {
+                               b = reader.ReadByte();
+
+                               ret = ret | ((b & 0x7f) << shift);
+                               shift += 7;
+                       } while ((b & 0x80) == 0x80);
+                       
+                       return ret;
+               }
+
+               internal void Deserialize (BinaryReader reader)
+               {
+                       int count = DecodeInt (reader);
+                       element = reader.ReadString ();
+                       caption = reader.ReadString ();
+
+                       if (count == 0)
+                               return;
+               
+                       nodes = new List<Node> (count);
+                       for (int i = 0; i < count; i++) {
+                               int child_address = DecodeInt (reader);
+                                                             
+                               Node t = new Node (this, -child_address);
+                               nodes.Add (t);
+                       }
+               }
+
+               internal void Serialize (FileStream output, BinaryWriter writer)
+               {
+                       if (nodes != null)
+                               foreach (Node child in nodes)
+                                       child.Serialize (output, writer);
+
+                       address = (int) output.Position;
+                       EncodeInt (writer, nodes == null ? 0 : (int) nodes.Count);
+                       writer.Write (element);
+                       writer.Write (caption);
+
+                       if (nodes != null)
+                               foreach (Node child in nodes)
+                                       EncodeInt (writer, child.address);
+               }
+
+               public void Sort ()
+               {
+                       if (nodes != null)
+                               nodes.Sort ();
+               }
+
+               internal string GetInternalUrl ()
+               {
+                       EnsureLoaded ();
+                       if (element.IndexOf (":") != -1 || parent == null)
+                               return element;
+
+                       var parentUrl = parent.GetInternalUrl ();
+                       return parentUrl.EndsWith ("/") ? parentUrl + element : parentUrl + "/" + element;
+               }
+               
+               public string PublicUrl {
+                       get {
+                               if (pubUrl != null)
+                                       return pubUrl;
+                               return pubUrl = tree.HelpSource != null ? tree.HelpSource.GetPublicUrl (this) : GetInternalUrl ();
+                       }
+               }
+
+               int IComparable.CompareTo (object obj)
+               {
+                       Node other = obj as Node;
+                       if (other == null)
+                               return -1;
+                       return CompareToInternal (other);
+               }
+
+               int IComparable<Node>.CompareTo (Node obj)
+               {
+                       return CompareToInternal (obj);
+               }
+
+               int CompareToInternal (Node other)
+               {
+                       EnsureLoaded ();
+                       other.EnsureLoaded ();
+
+                       var cap1 = caption;
+                       var cap2 = other.caption;
+
+                       /* Some node (notably from ecmaspec) have number prepended to them
+                        * which we need to sort better by padding them to the same number
+                        * of digits
+                        */
+                       if (char.IsDigit (cap1[0]) && char.IsDigit (cap2[0])) {
+                               int c1 = cap1.TakeWhile (char.IsDigit).Count ();
+                               int c2 = cap2.TakeWhile (char.IsDigit).Count ();
+                               
+                               if (c1 != c2) {
+                                       cap1 = cap1.PadLeft (cap1.Length + Math.Max (0, c2 - c1), '0');
+                                       cap2 = cap2.PadLeft (cap2.Length + Math.Max (0, c1 - c2), '0');
+                               }
+                       }
+
+                       return string.Compare (cap1, cap2, StringComparison.Ordinal);
+               }
+       }
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/Provider.cs b/mcs/tools/monkeydoc/MonkeyDoc/Provider.cs
new file mode 100644 (file)
index 0000000..03c54e5
--- /dev/null
@@ -0,0 +1,27 @@
+using System;
+
+namespace MonkeyDoc
+{
+       public abstract class Provider
+       {
+               //
+               // This code is used to "tag" all the different sources
+               //
+               static short serial;
+
+               public int Code { get; set; }
+
+               public Provider ()
+               {
+                       Code = serial++;
+               }
+
+               public abstract void PopulateTree (Tree tree);
+
+               //
+               // Called at shutdown time after the tree has been populated to perform
+               // any fixups or final tasks.
+               //
+               public abstract void CloseTree (HelpSource hs, Tree tree);
+       }
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/RootTree.cs b/mcs/tools/monkeydoc/MonkeyDoc/RootTree.cs
new file mode 100644 (file)
index 0000000..9725655
--- /dev/null
@@ -0,0 +1,522 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Configuration;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Xml;
+
+using MonkeyDoc.Providers;
+using Lucene.Net.Analysis.Standard;
+using Lucene.Net.Index;
+
+namespace MonkeyDoc
+{
+       public class RootTree : Tree
+       {
+               public const int MonodocVersion = 2;
+               const string RootNamespace = "root:/";
+               string basedir;
+               static List<string> uncompiledHelpSourcePaths = new List<string>();
+               HashSet<string> loadedSourceFiles = new HashSet<string>();
+               List<HelpSource> helpSources = new List<HelpSource>();
+               Dictionary<string, Node> nameToNode = new Dictionary<string, Node>();
+               Dictionary<string, HelpSource> nameToHelpSource = new Dictionary<string, HelpSource>();
+
+               public IList<HelpSource> HelpSources {
+                       get {
+                               return this.helpSources.AsReadOnly();
+                       }
+               }
+
+               public DateTime LastHelpSourceTime {
+                       get;
+                       set;
+               }
+
+               static bool IsUnix {
+                       get {
+                               int platform = (int)Environment.OSVersion.Platform;
+                               return platform == 4 || platform == 128 || platform == 6;
+                       }
+               }
+
+               RootTree () : base (null, "Mono Documentation", "root:")
+               {
+                       base.RootNode.EnsureNodes();
+                       this.LastHelpSourceTime = DateTime.Now;
+               }
+
+               public static void AddUncompiledSource (string path)
+               {
+                       uncompiledHelpSourcePaths.Add (path);
+               }
+
+               public static RootTree LoadTree ()
+               {
+                       return RootTree.LoadTree (RootTree.ProbeBaseDirectories ());
+               }
+
+               static string ProbeBaseDirectories ()
+               {
+                       string result = ".";
+                       try {
+                               result = Settings.Get ("docPath") ?? ".";
+                       } catch {}
+
+                       return result;
+               }
+
+               public static RootTree LoadTree (string basedir, bool includeExternal = true)
+               {
+                       if (string.IsNullOrEmpty (basedir))
+                               throw new ArgumentNullException ("basedir");
+                       if (!Directory.Exists (basedir))
+                               throw new ArgumentException ("basedir", string.Format ("Base documentation directory at '{0}' doesn't exist", basedir));
+
+                       XmlDocument xmlDocument = new XmlDocument ();
+                       string filename = Path.Combine (basedir, "monodoc.xml");
+                       xmlDocument.Load (filename);
+                       IEnumerable<string> sourceFiles = Directory.EnumerateFiles (Path.Combine (basedir, "sources"), "*.source");
+                       if (includeExternal)
+                               sourceFiles = sourceFiles.Concat (RootTree.ProbeExternalDirectorySources ());
+                       return RootTree.LoadTree (basedir, xmlDocument, sourceFiles);
+               }
+
+               static IEnumerable<string> ProbeExternalDirectorySources ()
+               {
+                       IEnumerable<string> enumerable = Enumerable.Empty<string> ();
+                       try {
+                               string path = Settings.Get ("docExternalPath");
+                               enumerable = enumerable.Concat (System.IO.Directory.EnumerateFiles (path, "*.source"));
+                       }
+                       catch {}
+
+                       if (Directory.Exists ("/Library/Frameworks/Mono.framework/External/monodoc"))
+                               enumerable = enumerable.Concat (Directory.EnumerateFiles ("/Library/Frameworks/Mono.framework/External/monodoc", "*.source"));
+                       return enumerable;
+               }
+
+               public static RootTree LoadTree (string indexDir, XmlDocument docTree, IEnumerable<string> sourceFiles)
+               {
+                       if (docTree == null) {
+                               docTree = new XmlDocument ();
+                               using  (Stream manifestResourceStream = typeof (RootTree).Assembly.GetManifestResourceStream ("monodoc.xml")) {
+                                       docTree.Load (manifestResourceStream);
+                               }
+                       }
+
+                       sourceFiles =  (sourceFiles ?? new string[0]);
+                       RootTree rootTree = new RootTree ();
+                       rootTree.basedir = indexDir;
+                       XmlNodeList xml_node_list = docTree.SelectNodes ("/node/node");
+                       rootTree.nameToNode["root"] = rootTree.RootNode;
+                       rootTree.nameToNode["libraries"] = rootTree.RootNode;
+                       rootTree.Populate (rootTree.RootNode, xml_node_list);
+
+                       if (rootTree.LookupEntryPoint ("various") == null) {
+                               Console.Error.WriteLine ("No 'various' doc node! Check monodoc.xml!");
+                               Node rootNode = rootTree.RootNode;
+                       }
+
+                       foreach (string current in sourceFiles)
+                               rootTree.AddSourceFile (current);
+
+                       foreach (string path in uncompiledHelpSourcePaths) {
+                               var hs = new Providers.EcmaUncompiledHelpSource (path);
+                               hs.RootTree = rootTree;
+                               rootTree.helpSources.Add (hs);
+                               string epath = "extra-help-source-" + hs.Name;
+                               Node hsn = rootTree.RootNode.CreateNode (hs.Name, "root:/" + epath);
+                               rootTree.nameToHelpSource [epath] = hs;
+                               hsn.EnsureNodes ();
+                               foreach (Node n in hs.Tree.RootNode.Nodes)
+                                       hsn.AddNode (n);
+                       }
+
+                       RootTree.PurgeNode (rootTree.RootNode);
+                       rootTree.RootNode.Sort ();
+                       return rootTree;
+               }
+
+               public void AddSource (string sourcesDir)
+               {
+                       IEnumerable<string> enumerable = Directory.EnumerateFiles (sourcesDir, "*.source");
+                       foreach (string current in enumerable)
+                               if (!this.AddSourceFile (current))
+                                       Console.Error.WriteLine ("Error: Could not load source file {0}", current);
+               }
+
+               public bool AddSourceFile (string sourceFile)
+               {
+                       if (this.loadedSourceFiles.Contains (sourceFile))
+                               return false;
+
+                       Node node = this.LookupEntryPoint ("various") ?? base.RootNode;
+                       XmlDocument xmlDocument = new XmlDocument ();
+                       try {
+                               xmlDocument.Load (sourceFile);
+                       } catch {
+                               bool result = false;
+                               return result;
+                       }
+
+                       XmlNodeList extra_nodes = xmlDocument.SelectNodes ("/monodoc/node");
+                       if (extra_nodes.Count > 0)
+                               this.Populate (node, extra_nodes);
+
+                       XmlNodeList sources = xmlDocument.SelectNodes ("/monodoc/source");
+                       if (sources == null) {
+                               Console.Error.WriteLine ("Error: No <source> section found in the {0} file", sourceFile);
+                               return false;
+                       }
+
+                       loadedSourceFiles.Add (sourceFile);
+                       foreach (XmlNode xmlNode in sources) {
+                               XmlAttribute a = xmlNode.Attributes["provider"];
+                               if (a == null) {
+                                       Console.Error.WriteLine ("Error: no provider in <source>");
+                                       continue;
+                               }
+                               string provider = a.InnerText;
+                               a = xmlNode.Attributes["basefile"];
+                               if (a == null) {
+                                       Console.Error.WriteLine ("Error: no basefile in <source>");
+                                       continue;
+                               }
+                               string basefile = a.InnerText;
+                               a = xmlNode.Attributes["path"];
+                               if (a == null) {
+                                       Console.Error.WriteLine ("Error: no path in <source>");
+                                       continue;
+                               }
+                               string path = a.InnerText;
+                               string basefilepath = Path.Combine (Path.GetDirectoryName (sourceFile), basefile);
+                               HelpSource helpSource = RootTree.GetHelpSource (provider, basefilepath);
+                               if (helpSource != null) {
+                                       helpSource.RootTree = this;
+                                       this.helpSources.Add (helpSource);
+                                       this.nameToHelpSource[path] = helpSource;
+                                       Node node2 = this.LookupEntryPoint (path);
+                                       if (node2 == null) {
+                                               Console.Error.WriteLine ("node `{0}' is not defined on the documentation map", path);
+                                               node2 = node;
+                                       }
+                                       foreach (Node current in helpSource.Tree.RootNode.Nodes) {
+                                               node2.AddNode (current);
+                                       }
+                                       node2.Sort ();
+                               }
+                       }
+                       return true;
+               }
+
+               static bool PurgeNode (Node node)
+               {
+                       bool result = false;
+                       if (!node.Documented)
+                       {
+                               List<Node> list = new List<Node> ();
+                               foreach (Node current in node.Nodes)
+                               {
+                                       bool flag = RootTree.PurgeNode (current);
+                                       if (flag)
+                                       {
+                                               list.Add (current);
+                                       }
+                               }
+                               result =  (node.Nodes.Count == list.Count);
+                               foreach (Node current2 in list)
+                               {
+                                       node.DeleteNode (current2);
+                               }
+                       }
+                       return result;
+               }
+
+               public static string[] GetSupportedFormats ()
+               {
+                       return new string[]
+                       {
+                               "ecma",
+                               "ecmaspec",
+                               "error",
+                               "man",
+                               "xhtml"
+                       };
+               }
+
+               public static HelpSource GetHelpSource (string provider, string basefilepath)
+               {
+                       HelpSource result;
+                       try {
+                               switch (provider) {
+                               case "xhtml":
+                               case "hb":
+                                       result = new XhtmlHelpSource (basefilepath, false);
+                                       break;
+                               case "man":
+                                       result = new ManHelpSource (basefilepath, false);
+                                       break;
+                               case "error":
+                                       result = new ErrorHelpSource (basefilepath, false);
+                                       break;
+                               case "ecmaspec":
+                                       result = new EcmaSpecHelpSource (basefilepath, false);
+                                       break;
+                               case "ecma":
+                                       result = new EcmaHelpSource (basefilepath, false);
+                                       break;
+                               default:
+                                       Console.Error.WriteLine ("Error: Unknown provider specified: {0}", provider);
+                                       result = null;
+                                       break;
+                               }
+                       } catch (FileNotFoundException) {
+                               Console.Error.WriteLine ("Error: did not find one of the files in sources/" + basefilepath);
+                               result = null;
+                       }
+                       return result;
+               }
+
+               public static Provider GetProvider (string provider, params string[] basefilepaths)
+               {
+                       switch (provider) {
+                       case "ecma":
+                               return new EcmaProvider (basefilepaths[0]);
+                       case "ecmaspec":
+                               return new EcmaSpecProvider (basefilepaths[0]);
+                       case "error":
+                               return new ErrorProvider (basefilepaths[0]);
+                       case "man":
+                               return new ManProvider (basefilepaths);
+                       case "xhml":
+                       case "hb":
+                               return new XhtmlProvider (basefilepaths[0]);
+                       }
+
+                       throw new NotSupportedException (provider);
+               }
+
+               void Populate (Node parent, XmlNodeList xml_node_list)
+               {
+                       foreach (XmlNode xmlNode in xml_node_list) {
+                               XmlAttribute e = xmlNode.Attributes["parent"];
+                               Node parent2 = null;
+                               if (e != null && this.nameToNode.TryGetValue (e.InnerText, out parent2)) {
+                                       xmlNode.Attributes.Remove (e);
+                                       Populate (parent2, xmlNode.SelectNodes ("."));
+                                       continue;
+                               }
+                               e = xmlNode.Attributes["label"];
+                               if (e == null) {
+                                       Console.Error.WriteLine ("`label' attribute missing in <node>");
+                                       continue;
+                               }
+                               string label = e.InnerText;
+                               e = xmlNode.Attributes["name"];
+                               if (e == null) {
+                                       Console.Error.WriteLine ("`name' attribute missing in <node>");
+                                       continue;
+                               }
+                               string name = e.InnerText;
+                               Node orCreateNode = parent.GetOrCreateNode (label, "root:/" + name);
+                               orCreateNode.EnsureNodes ();
+                               this.nameToNode[name] = orCreateNode;
+                               XmlNodeList xmlNodeList = xmlNode.SelectNodes ("./node");
+                               if (xmlNodeList != null) {
+                                       this.Populate (orCreateNode, xmlNodeList);
+                               }
+                       }
+               }
+
+               public Node LookupEntryPoint (string name)
+               {
+                       Node result = null;
+                       if (!this.nameToNode.TryGetValue (name, out result)) {
+                               result = null;
+                       }
+                       return result;
+               }
+
+               public TOutput RenderUrl<TOutput> (string url, IDocGenerator<TOutput> generator, HelpSource hintSource = null)
+               {
+                       Node dummy;
+                       return RenderUrl<TOutput> (url, generator, out dummy, hintSource);
+               }
+
+               public TOutput RenderUrl<TOutput> (string url, IDocGenerator<TOutput> generator, out Node node, HelpSource hintSource = null)
+               {
+                       node = null;
+                       string internalId = null;
+                       HelpSource hs = GetHelpSourceAndIdForUrl (url, hintSource, out internalId, out node);
+                       return generator.Generate (hs, internalId);
+               }
+
+               public HelpSource GetHelpSourceAndIdForUrl (string url, out string internalId)
+               {
+                       Node dummy;
+                       return GetHelpSourceAndIdForUrl (url, out internalId, out dummy);
+               }
+
+               public HelpSource GetHelpSourceAndIdForUrl (string url, out string internalId, out Node node)
+               {
+                       return GetHelpSourceAndIdForUrl (url, null, out internalId, out node);
+               }
+
+               public HelpSource GetHelpSourceAndIdForUrl (string url, HelpSource hintSource, out string internalId, out Node node)
+               {
+                       node = null;
+                       internalId = null;
+
+                       if (url.StartsWith ("root:/", StringComparison.OrdinalIgnoreCase))
+                               return this.GetHelpSourceAndIdFromName (url.Substring ("root:/".Length), out internalId, out node);
+
+                       HelpSource helpSource = hintSource;
+                       if (helpSource == null || string.IsNullOrEmpty (internalId = helpSource.GetInternalIdForUrl (url, out node))) {
+                               helpSource = null;
+                               foreach (var hs in helpSources.Where (h => h.CanHandleUrl (url))) {
+                                       if (!string.IsNullOrEmpty (internalId = hs.GetInternalIdForUrl (url, out node))) {
+                                               helpSource = hs;
+                                               break;
+                                       }
+                               }
+                       }
+
+                       return helpSource;
+               }
+
+               public HelpSource GetHelpSourceAndIdFromName (string name, out string internalId, out Node node)
+               {
+                       internalId = "root:";
+                       node = this.LookupEntryPoint (name);
+
+                       return node == null ? null : node.Nodes.Select (n => n.Tree.HelpSource).Where (hs => hs != null).Distinct ().FirstOrDefault ();
+               }
+
+               public HelpSource GetHelpSourceFromId (int id)
+               {
+                       return  (id < 0 || id >= this.helpSources.Count) ? null : this.helpSources[id];
+               }
+
+               public Stream GetImage (string url)
+               {
+                       if (url.StartsWith ("source-id:", StringComparison.OrdinalIgnoreCase)) {
+                               string text = url.Substring (10);
+                               int num = text.IndexOf (":");
+                               string text2 = text.Substring (0, num);
+                               int id = 0;
+                               try {
+                                       id = int.Parse (text2);
+                               } catch {
+                                       Console.Error.WriteLine ("Failed to parse source-id url: {0} `{1}'", url, text2);
+                                       return null;
+                               }
+                               HelpSource helpSourceFromId = this.GetHelpSourceFromId (id);
+                               return helpSourceFromId.GetImage (text.Substring (num + 1));
+                       }
+                       Assembly assembly = Assembly.GetAssembly (typeof (RootTree));
+                       return assembly.GetManifestResourceStream (url);
+               }
+
+               public IndexReader GetIndex ()
+               {
+                       try {
+                               string text = Path.Combine (this.basedir, "monodoc.index");
+                               if (File.Exists (text))
+                                       return IndexReader.Load (text);
+
+                               text = Path.Combine (Settings.Get ("monodocIndexDirectory"), "monodoc.index");
+                               return IndexReader.Load (text);
+                       } catch {
+                               return null;
+                       }
+               }
+
+               public static void MakeIndex ()
+               {
+                       RootTree rootTree = RootTree.LoadTree ();
+                       rootTree.GenerateIndex ();
+               }
+
+               public void GenerateIndex ()
+               {
+                       IndexMaker indexMaker = new IndexMaker ();
+                       foreach (HelpSource current in this.helpSources)
+                               current.PopulateIndex (indexMaker);
+                       string text = Path.Combine (this.basedir, "monodoc.index");
+                       try {
+                               indexMaker.Save (text);
+                       } catch (UnauthorizedAccessException) {
+                               text = Path.Combine (Settings.Get ("docPath"), "monodoc.index");
+                               try {
+                                       indexMaker.Save (text);
+                               } catch (UnauthorizedAccessException) {
+                                       Console.WriteLine ("Unable to write index file in {0}", Path.Combine (Settings.Get ("docPath"), "monodoc.index"));
+                                       return;
+                               }
+                       }
+                       if (RootTree.IsUnix)
+                               RootTree.chmod (text, 420);
+
+                       Console.WriteLine ("Documentation index at {0} updated", text);
+               }
+
+               public SearchableIndex GetSearchIndex ()
+               {
+                       try {
+                               string text = Path.Combine (this.basedir, "search_index");
+                               if (System.IO.Directory.Exists (text))
+                                       return SearchableIndex.Load (text);
+                               text = Path.Combine (Settings.Get ("docPath"), "search_index");
+                               return SearchableIndex.Load (text);
+                       } catch {
+                               return null;
+                       }
+               }
+
+               public static void MakeSearchIndex ()
+               {
+                       RootTree rootTree = RootTree.LoadTree ();
+                       rootTree.GenerateSearchIndex ();
+               }
+
+               public void GenerateSearchIndex ()
+               {
+                       Console.WriteLine ("Loading the monodoc tree...");
+                       string text = Path.Combine (this.basedir, "search_index");
+                       IndexWriter indexWriter;
+                       var analyzer = new StandardAnalyzer (Lucene.Net.Util.Version.LUCENE_CURRENT);
+                       var directory = Lucene.Net.Store.FSDirectory.Open (text);
+
+                       try {
+                               if (!Directory.Exists (text))
+                                       Directory.CreateDirectory (text);
+                               indexWriter = new IndexWriter (directory, analyzer, true, IndexWriter.MaxFieldLength.LIMITED);
+                       } catch (UnauthorizedAccessException) {
+                               try {
+                                       text = Path.Combine (Settings.Get ("docPath"), "search_index");
+                                       if (!Directory.Exists (text))
+                                               Directory.CreateDirectory (text);
+                                       indexWriter = new IndexWriter (directory, analyzer, true, IndexWriter.MaxFieldLength.LIMITED);
+                               } catch (UnauthorizedAccessException) {
+                                       Console.WriteLine ("You don't have permissions to write on " + text);
+                                       return;
+                               }
+                       }
+                       Console.WriteLine ("Collecting and adding documents...");
+                       foreach (HelpSource current in this.helpSources) {
+                               current.PopulateSearchableIndex (indexWriter);
+                       }
+                       Console.WriteLine ("Closing...");
+                       indexWriter.Optimize ();
+                       indexWriter.Close ();
+               }
+
+               [DllImport ("libc")]
+               static extern int chmod (string filename, int mode);
+       }
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/SearchableDocument.cs b/mcs/tools/monkeydoc/MonkeyDoc/SearchableDocument.cs
new file mode 100644 (file)
index 0000000..eebcc3a
--- /dev/null
@@ -0,0 +1,66 @@
+//
+//
+// SearchableDocument.cs: Abstracts our model of document from the Lucene Document 
+//
+// Author: Mario Sopena
+//
+using Lucene.Net.Documents;
+
+namespace MonkeyDoc
+{
+       struct SearchableDocument
+       {
+               public string Title {
+                       get; set;
+               }
+
+               public string Url {
+                       get; set;
+               }
+
+               public string FullTitle {
+                       get; set;
+               }
+
+               public string HotText {
+                       get; set;
+               }
+
+               public string Text {
+                       get; set;
+               }
+
+               public string Examples {
+                       get; set;
+               }
+
+               public SearchableDocument Reset ()
+               {
+                       Title = Url = FullTitle = HotText = Text = Examples = null;
+                       return this;
+               }
+
+               public Document LuceneDoc {
+                       get {
+                               Document doc = new Document ();
+                               doc.Add (UnIndexed ("title", Title));
+                               doc.Add (UnIndexed ("url", Url));
+                               doc.Add (UnIndexed ("fulltitle", FullTitle ?? string.Empty));
+                               doc.Add (UnStored ("hottext", HotText));
+                               doc.Add (UnStored ("text", Text));
+                               doc.Add (UnStored ("examples", Examples));
+                               return doc;
+                       }
+               }
+
+               static Field UnIndexed(System.String name, System.String value_Renamed)
+               {
+                       return new Field(name, value_Renamed, Field.Store.YES, Field.Index.NO);
+               }
+
+               static Field UnStored(System.String name, System.String value_Renamed)
+               {
+                       return new Field(name, value_Renamed, Field.Store.NO, Field.Index.ANALYZED);
+               }
+       }
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/SearchableIndex.cs b/mcs/tools/monkeydoc/MonkeyDoc/SearchableIndex.cs
new file mode 100644 (file)
index 0000000..7eb24fe
--- /dev/null
@@ -0,0 +1,179 @@
+//
+//
+// SearchableIndex.cs: Index that uses Lucene to search through the docs 
+//
+// Author: Mario Sopena
+//
+
+using System;
+using System.IO;
+using System.Collections.Generic;
+// Lucene imports
+using Lucene.Net.Index;
+using Lucene.Net.Documents;
+using Lucene.Net.Analysis;
+using Lucene.Net.Analysis.Standard;
+using Lucene.Net.Search;
+using Lucene.Net.QueryParsers;
+using Lucene.Net.Store;
+
+namespace MonkeyDoc
+{
+       public class SearchableIndex 
+       {
+               const int maxSearchCount = 30;
+
+               IndexSearcher searcher;
+               string dir;
+
+               public string Dir {
+                       get { 
+                               if (dir == null)
+                                       dir = "search_index";
+                               return dir;
+                       }
+                       set { dir = value; }
+               }
+
+               public static SearchableIndex Load (string dir)
+               {
+                       SearchableIndex s = new SearchableIndex ();
+                       s.dir = dir;
+                       try {
+                               //s.searcher = new IndexSearcher (dir);
+                               // TODO: parametrize that depending if we run on the desktop (low footprint) or the server (use RAMDirectory for instance)
+                               s.searcher = new IndexSearcher (FSDirectory.Open (dir));
+                       } catch (IOException) {
+                               Console.WriteLine ("Index nonexistent or in bad format");
+                               return null;
+                       }
+                       return s;
+               }
+               
+               public Result Search (string term)
+               {
+                       return Search (term, maxSearchCount);
+               }
+
+               public Result Search (string term, int count)
+               {
+                       return Search (term, count, 0);
+               }
+
+               public Result Search (string term, int count, int start) {
+                       try {
+                               term = term.ToLower ();
+                               Term htTerm = new Term ("hottext", term);
+                               Query qq1 = new FuzzyQuery (htTerm);
+                               Query qq2 = new TermQuery (htTerm);
+                               qq2.Boost = 10f;
+                               Query qq3 = new PrefixQuery (htTerm);
+                               qq3.Boost = 10f;
+                               DisjunctionMaxQuery q1 = new DisjunctionMaxQuery (0f);
+                               q1.Add (qq1);
+                               q1.Add (qq2);
+                               q1.Add (qq3);
+                               Query q2 = new TermQuery (new Term ("text", term));
+                               q2.Boost = 3f;
+                               Query q3 = new TermQuery (new Term ("examples", term));
+                               q3.Boost = 3f;
+                               DisjunctionMaxQuery q = new DisjunctionMaxQuery (0f);
+
+                               q.Add (q1);
+                               q.Add (q2);
+                               q.Add (q3);
+                       
+                               TopDocs top = SearchInternal (q, count, start);
+                               Result r = new Result (term, searcher, top.ScoreDocs);
+                               return r;
+                       } catch (IOException) {
+                               Console.WriteLine ("No index in {0}", dir);
+                               return null;
+                       }
+               }
+
+               TopDocs SearchInternal (Query q, int count, int start)
+               {
+                       // Easy path that doesn't involve creating a Collector ourselves
+                       // watch for Lucene.NET improvement on that (like searcher.SearchAfter)
+                       if (start == 0)
+                               return searcher.Search (q, count);
+
+                       var weight = searcher.CreateWeight (q); // TODO: reuse weight instead of query
+                       var collector = TopScoreDocCollector.Create (start + count + 1, false);
+                       searcher.Search (q, collector);
+
+                       return collector.TopDocs (start, count);
+               }
+
+               public Result FastSearch (string term, int number)
+               {
+                       try {
+                               term = term.ToLower ();
+                               Query q1 = new TermQuery (new Term ("hottext", term));
+                               Query q2 = new PrefixQuery (new Term ("hottext", term));
+                               q2.Boost = 0.5f;
+                               DisjunctionMaxQuery q = new DisjunctionMaxQuery (0f);
+                               q.Add (q1);
+                               q.Add (q2);
+                               TopDocs top = searcher.Search (q, number);
+                               return new Result (term, searcher, top.ScoreDocs);
+                       } catch (IOException) {
+                               Console.WriteLine ("No index in {0}", dir);
+                               return null;
+                       }
+               }
+       }
+
+       //
+       // An object representing the search term with the results
+       // 
+       public class Result {
+               string term;
+               Searcher searcher;
+               ScoreDoc[] docs;
+
+               public string Term {
+                       get { return term;}
+               }
+
+               public int Count {
+                       get { return docs.Length; }
+               }
+
+               public Document this [int i] {
+                       get { return searcher.Doc (docs[i].Doc); }
+               }
+       
+               public string GetTitle (int i) 
+               {
+                       Document d = this[i];
+                       return d == null ? string.Empty : d.Get ("title");
+               }
+
+               public string GetUrl (int i)
+               {
+                       Document d = this[i];
+                       return d == null ? string.Empty : d.Get ("url");
+               }
+
+               public string GetFullTitle (int i)
+               {
+                       Document d = this[i];
+                       return d == null ? string.Empty : d.Get ("fulltitle");
+               }
+
+               public float Score (int i)
+               {
+                       return docs[i].Score;
+               }
+
+               public Result (string Term, Searcher searcher, ScoreDoc[] docs) 
+               {
+                       this.term = Term;
+                       this.searcher = searcher;
+                       this.docs = docs;
+               }
+       }
+}
+
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/Tree.cs b/mcs/tools/monkeydoc/MonkeyDoc/Tree.cs
new file mode 100644 (file)
index 0000000..a9b3367
--- /dev/null
@@ -0,0 +1,164 @@
+using System;
+using System.IO;
+using System.Text;
+using System.Linq;
+using System.Xml;
+using System.Collections.Generic;
+
+namespace MonkeyDoc
+{
+       /// <summary>
+       ///    This tree is populated by the documentation providers, or populated
+       ///    from a binary encoding of the tree.  The format of the tree is designed
+       ///    to minimize the need to load it in full.
+       /// </summary>
+
+       /* Ideally this class should also be abstracted to let user have something
+        * else than a file as a backing store, a database for instance
+        */
+       public class Tree
+       {
+               public readonly HelpSource HelpSource;
+       
+               FileStream InputStream;
+               BinaryReader InputReader;
+
+               // This is the node which contains all the other node of the tree
+               Node rootNode;
+
+               /// <summary>
+               ///   Load from file constructor
+               /// </summary>
+               public Tree (HelpSource hs, string filename)
+               {
+                       Encoding utf8 = new UTF8Encoding (false, true);
+
+                       if (!File.Exists (filename)){
+                               throw new FileNotFoundException ();
+                       }
+               
+                       InputStream = File.OpenRead (filename);
+                       InputReader = new BinaryReader (InputStream, utf8);
+                       byte [] sig = InputReader.ReadBytes (4);
+               
+                       if (!GoodSig (sig))
+                               throw new Exception ("Invalid file format");
+               
+                       InputStream.Position = 4;
+                       var position = InputReader.ReadInt32 ();
+                       rootNode = new Node (this, position);
+                       InflateNode (rootNode);
+
+                       HelpSource = hs;
+               }
+
+               /// <summary>
+               ///    Tree creation and merged tree constructor
+               /// </summary>
+               public Tree (HelpSource hs, string caption, string url) : this (hs, null, caption, url)
+               {
+               }
+
+               public Tree (HelpSource hs, Node parent, string caption, string element)
+               {
+                       HelpSource = hs;
+                       rootNode = parent == null ? new Node (this, caption, element) : new Node (parent, caption, element);
+               }
+
+               /// <summary>
+               ///    Saves the tree into the specified file using the help file format.
+               /// </summary>
+               public void Save (string file)
+               {
+                       Encoding utf8 = new UTF8Encoding (false, true);
+                       using (FileStream output = File.OpenWrite (file)){
+                               // Skip over the pointer to the first node.
+                               output.Position = 8;
+                       
+                               using (BinaryWriter writer = new BinaryWriter (output, utf8)) {
+                                       // Recursively dump
+                                       rootNode.Serialize (output, writer);
+
+                                       output.Position = 0;
+                                       writer.Write (new byte [] { (byte) 'M', (byte) 'o', (byte) 'H', (byte) 'P' });
+                                       writer.Write (rootNode.Address);
+                               }
+                       }
+               }
+
+               public Node RootNode {
+                       get {
+                               return rootNode;
+                       }
+               }
+
+               static bool GoodSig (byte [] sig)
+               {
+                       if (sig.Length != 4)
+                               return false;
+                       return sig [0] == (byte) 'M'
+                               && sig [1] == (byte) 'o'
+                           && sig [2] == (byte) 'H'
+                               && sig [3] == (byte) 'P';
+               }
+
+               public void InflateNode (Node baseNode)
+               {
+                       var address = baseNode.Address;
+                       if (address < 0)
+                               address = -address;
+
+                       InputStream.Position = address;
+                       baseNode.Deserialize (InputReader);
+               }
+       }
+
+       public static class TreeDumper
+       {
+               static int indent;
+
+               static void Indent ()
+               {
+                       for (int i = 0; i < indent; i++)
+                               Console.Write ("   ");
+               }
+       
+               public static void PrintTree (Node node)
+               {
+                       Indent ();
+                       Console.WriteLine ("{0},{1}\t[PublicUrl: {2}]", node.Element, node.Caption, node.PublicUrl);
+                       if (node.Nodes.Count == 0)
+                               return;
+
+                       indent++;
+                       foreach (Node n in node.Nodes)
+                               PrintTree (n);
+                       indent--;
+               }
+
+               public static string ExportToTocXml (Node root, string title, string desc)
+               {
+                       if (root == null)
+                               throw new ArgumentNullException ("root");
+                       // Return a toc index of sub-nodes
+                       StringBuilder buf = new StringBuilder ();
+                       var writer = XmlWriter.Create (buf);
+                       writer.WriteStartElement ("toc");
+                       writer.WriteAttributeString ("title", title ?? string.Empty);
+                       writer.WriteElementString ("description", desc ?? string.Empty);
+                       writer.WriteStartElement ("list");
+                       foreach (Node n in root.Nodes) {
+                               writer.WriteStartElement ("item");
+                               writer.WriteAttributeString ("url", n.Element);
+                               writer.WriteValue (n.Caption);
+                               writer.WriteEndElement ();
+                       }
+                       writer.WriteEndElement ();
+                       writer.WriteEndElement ();
+                       writer.Flush ();
+                       writer.Close ();
+
+                       return buf.ToString ();
+               }
+       }
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/TypeUtils.cs b/mcs/tools/monkeydoc/MonkeyDoc/TypeUtils.cs
new file mode 100644 (file)
index 0000000..2e75663
--- /dev/null
@@ -0,0 +1,40 @@
+using System;
+
+namespace MonkeyDoc
+{
+       public static class TypeUtils
+       {
+               public static bool GetNamespaceAndType (string url, out string ns, out string type)
+               {
+                       int nsidx = -1;
+                       int numLt = 0;
+                       for (int i = 0; i < url.Length; ++i) {
+                               char c = url [i];
+                               switch (c) {
+                               case '<':
+                               case '{':
+                                       ++numLt;
+                                       break;
+                               case '>':
+                               case '}':
+                                       --numLt;
+                                       break;
+                               case '.':
+                                       if (numLt == 0)
+                                               nsidx = i;
+                                       break;
+                               }
+                       }
+
+                       if (nsidx == -1) {
+                               ns = null;
+                               type = null;
+                               return false;
+                       }
+                       ns = url.Substring (0, nsidx);
+                       type = url.Substring (nsidx + 1);
+               
+                       return true;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/cache.cs b/mcs/tools/monkeydoc/MonkeyDoc/cache.cs
new file mode 100644 (file)
index 0000000..1c26f05
--- /dev/null
@@ -0,0 +1,53 @@
+using System;
+using System.Linq;
+using System.IO;
+using System.Configuration;
+using System.Collections.Specialized;
+using MonkeyDoc.Caches;
+
+namespace MonkeyDoc
+{
+       public enum DocEntity
+       {
+               Text,
+               Blob
+       }
+
+       public interface IDocCache : IDisposable
+       {
+               bool IsCached (string id);
+               bool CanCache (DocEntity entity);
+
+               Stream GetCachedStream (string id);
+               string GetCachedString (string id);
+
+               void CacheText (string id, string content);
+               void CacheText (string id, Stream stream);
+
+               void CacheBlob (string id, byte[] data);
+               void CacheBlob (string id, Stream stream);
+       }
+
+       public static class DocCacheHelper
+       {
+               static string cacheBaseDirectory;
+
+               static DocCacheHelper ()
+               {
+                       try {
+                               var cacheValues = Settings.Get ("cache").Split (',');
+                               if (cacheValues.Length == 2 && cacheValues[0].Equals ("file", StringComparison.Ordinal))
+                                       cacheBaseDirectory = cacheValues[1].Replace ("~", Environment.GetFolderPath (Environment.SpecialFolder.Personal));
+                       } catch {}
+               }
+
+               // Use configuration option to query for cache directory, if it doesn't exist we instantiate a nullcache
+               public static IDocCache GetDefaultCache (string name)
+               {
+                       if (cacheBaseDirectory == null)
+                               return new NullCache ();
+
+                       return new FileCache (Path.Combine (cacheBaseDirectory, name));
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/caches/FileCache.cs b/mcs/tools/monkeydoc/MonkeyDoc/caches/FileCache.cs
new file mode 100644 (file)
index 0000000..333f33b
--- /dev/null
@@ -0,0 +1,75 @@
+using System;
+using System.IO;
+
+namespace MonkeyDoc.Caches
+{
+       public class FileCache : IDocCache
+       {
+               string baseCacheDir;
+
+               public FileCache (string baseCacheDir)
+               {
+                       this.baseCacheDir = baseCacheDir;
+                       if (!Directory.Exists (baseCacheDir))
+                               Directory.CreateDirectory (baseCacheDir);
+               }
+
+               public bool IsCached (string id)
+               {
+                       return File.Exists (MakePath (id));
+               }
+
+               public bool CanCache (DocEntity entity)
+               {
+                       return true;
+               }
+
+               public Stream GetCachedStream (string id)
+               {
+                       return File.OpenRead (MakePath (id));
+               }
+
+               public string GetCachedString (string id)
+               {
+                       return File.ReadAllText (MakePath (id));
+               }
+
+               public void CacheText (string id, string content)
+               {
+                       File.WriteAllText (MakePath (id), content);
+               }
+
+               public void CacheText (string id, Stream stream)
+               {
+                       using (var file = File.OpenWrite (MakePath (id)))
+                               stream.CopyTo (file);
+               }
+
+               public void CacheBlob (string id, byte[] data)
+               {
+                       File.WriteAllBytes (MakePath (id), data);
+               }
+
+               public void CacheBlob (string id, Stream stream)
+               {
+                       using (var file = File.OpenWrite (MakePath (id)))
+                               stream.CopyTo (file);
+               }
+
+               string MakePath (string id)
+               {
+                       id = id.Replace (Path.DirectorySeparatorChar, '_');
+                       return Path.Combine (baseCacheDir, id);
+               }
+
+               public void Dispose ()
+               {
+                       if (!Directory.Exists (baseCacheDir))
+                               return;
+
+                       try {
+                               Directory.Delete (baseCacheDir, true);
+                       } catch {}
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/caches/NullCache.cs b/mcs/tools/monkeydoc/MonkeyDoc/caches/NullCache.cs
new file mode 100644 (file)
index 0000000..1514d66
--- /dev/null
@@ -0,0 +1,54 @@
+using System;
+using System.IO;
+
+namespace MonkeyDoc.Caches
+{
+       // This is basically a no-cache implementation
+       public class NullCache : IDocCache
+       {
+               public bool IsCached (string id)
+               {
+                       return false;
+               }
+
+               public bool CanCache (DocEntity entity)
+               {
+                       return false;
+               }
+
+               public Stream GetCachedStream (string id)
+               {
+                       return null;
+               }
+
+               public string GetCachedString (string id)
+               {
+                       return null;
+               }
+
+               public void CacheText (string id, string content)
+               {
+
+               }
+
+               public void CacheText (string id, Stream stream)
+               {
+
+               }
+
+               public void CacheBlob (string id, byte[] data)
+               {
+
+               }
+
+               public void CacheBlob (string id, Stream stream)
+               {
+
+               }
+
+               public void Dispose ()
+               {
+                       
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/generator.cs b/mcs/tools/monkeydoc/MonkeyDoc/generator.cs
new file mode 100644 (file)
index 0000000..f0949b9
--- /dev/null
@@ -0,0 +1,27 @@
+using System;
+
+namespace MonkeyDoc
+{
+       // All type of documents that a generator may find as input
+       public enum DocumentType {
+               EcmaXml, // Our main monodoc format
+               EcmaSpecXml,
+               Man,
+               AddinXml,
+               MonoBook, // This is mostly XHTML already, just need a tiny bit of processing
+               Html,
+               TocXml, // Used by help source displaying some kind of toc of the content they host
+               PlainText,
+               ErrorXml
+       }
+
+       /* This interface defines a set of transformation engine
+        * that convert multiple documentation source to a single output format
+        */
+       public interface IDocGenerator<TOutput>
+       {
+               // This method is responsible for finding out the documentation type
+               // for the given ID and use the right engine internally
+               TOutput Generate (HelpSource hs, string internalId);
+       }
+}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/generators/HtmlGenerator.cs b/mcs/tools/monkeydoc/MonkeyDoc/generators/HtmlGenerator.cs
new file mode 100644 (file)
index 0000000..d7eeeb8
--- /dev/null
@@ -0,0 +1,132 @@
+using System;
+using System.IO;
+using System.Text;
+using System.Linq;
+using System.Collections.Generic;
+
+using MonkeyDoc;
+
+namespace MonkeyDoc.Generators
+{
+       using Html;
+
+       interface IHtmlExporter
+       {
+               string CssCode { get; }
+               string Export (Stream input, Dictionary<string, string> extras);
+               string Export (string input, Dictionary<string, string> extras);
+       }
+
+       public class HtmlGenerator : IDocGenerator<string>
+       {
+               const string cachePrefix = "htmlcached#";
+
+               static string css_code;
+
+               IDocCache defaultCache;
+               static Dictionary<DocumentType, IHtmlExporter> converters;
+
+               static HtmlGenerator ()
+               {
+                       converters = new Dictionary<DocumentType, IHtmlExporter> {
+                               { DocumentType.EcmaXml, new Ecma2Html () },
+                               { DocumentType.Man, new Man2Html () },
+                               { DocumentType.TocXml, new Toc2Html () },
+                               { DocumentType.EcmaSpecXml, new Ecmaspec2Html () },
+                               { DocumentType.ErrorXml, new Error2Html () },
+                               { DocumentType.Html, new Idem () },
+                               { DocumentType.MonoBook, new MonoBook2Html () },
+                               { DocumentType.AddinXml, new Addin2Html () },
+                               { DocumentType.PlainText, new Idem () },
+                       };
+               }
+
+               public HtmlGenerator (IDocCache defaultCache)
+               {
+                       this.defaultCache = defaultCache;
+               }
+
+               public string Generate (HelpSource hs, string id)
+               {
+                       if (hs == null || string.IsNullOrEmpty (id))
+                               return MakeHtmlError (string.Format ("Your request has found no candidate provider [hs=\"{0}\", id=\"{1}\"]",
+                                                                    hs == null ? "(null)" : hs.Name, id ?? "(null)"));
+                       var cache = defaultCache ?? hs.Cache;
+                       if (cache != null && cache.IsCached (MakeCacheKey (hs, id, null)))
+                               return cache.GetCachedString (MakeCacheKey (hs, id, null));
+
+                       IEnumerable<string> parts;
+                       if (hs.IsMultiPart (id, out parts))
+                               return GenerateMultiPart (hs, parts, id);
+
+                       if (hs.IsRawContent (id))
+                               return hs.GetText (id) ?? string.Empty;
+
+                       Dictionary<string, string> extraParams = null;
+                       DocumentType type = hs.GetDocumentTypeForId (id, out extraParams);
+                       if (cache != null && extraParams != null && cache.IsCached (MakeCacheKey (hs, id, extraParams)))
+                               return cache.GetCachedString (MakeCacheKey (hs, id, extraParams));
+
+                       IHtmlExporter exporter;
+                       if (!converters.TryGetValue (type, out exporter))
+                               return MakeHtmlError (string.Format ("Input type '{0}' not supported",
+                                                                    type.ToString ()));
+                       var result = hs.IsGeneratedContent (id) ? 
+                               exporter.Export (hs.GetCachedText (id), extraParams) :
+                               exporter.Export (hs.GetCachedHelpStream (id), extraParams);
+
+                       if (cache != null)
+                               cache.CacheText (MakeCacheKey (hs, id, extraParams), result);
+                       return result;
+               }
+
+               string GenerateMultiPart (HelpSource hs, IEnumerable<string> ids, string originalId)
+               {
+                       var sb = new StringBuilder ();
+                       foreach (var id in ids)
+                               sb.AppendLine (Generate (hs, id));
+
+                       var cache = defaultCache ?? hs.Cache;
+                       if (cache != null)
+                               cache.CacheText (MakeCacheKey (hs, originalId, null), sb.ToString ());
+                       return sb.ToString ();
+               }
+
+               public static string InlineCss {
+                       get {
+                               if (css_code != null)
+                                       return css_code;
+
+                               System.Reflection.Assembly assembly = System.Reflection.Assembly.GetAssembly (typeof (HtmlGenerator));
+                               Stream str_css = assembly.GetManifestResourceStream ("base.css");
+                               StringBuilder sb = new StringBuilder ((new StreamReader (str_css)).ReadToEnd());
+                               sb.Replace ("@@FONT_FAMILY@@", "Sans Serif");
+                               sb.Replace ("@@FONT_SIZE@@", "100%");
+                               css_code = sb.ToString () + converters.Values
+                                       .Select (c => c.CssCode)
+                                       .Where (css => !string.IsNullOrEmpty (css))
+                                       .DefaultIfEmpty (string.Empty)
+                                       .Aggregate (string.Concat);
+                               return css_code;
+                       }
+                       set { 
+                               css_code = value;
+                       }
+               }
+
+               string MakeHtmlError (string error)
+               {
+                       return string.Format ("<html><head></head><body><p>{0}</p></body></html>", error);
+               }
+
+               string MakeCacheKey (HelpSource hs, string page, IDictionary<string,string> extraParams)
+               {
+                       var key = cachePrefix + hs.SourceID + page;
+                       if (extraParams != null && extraParams.Count > 0) {
+                               var paramPart = string.Join ("-", extraParams.Select (kvp => kvp.Key + kvp.Value));
+                               key += '_' + paramPart;
+                       }
+                       return key;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/generators/RawGenerator.cs b/mcs/tools/monkeydoc/MonkeyDoc/generators/RawGenerator.cs
new file mode 100644 (file)
index 0000000..c1e4bb2
--- /dev/null
@@ -0,0 +1,41 @@
+using System;
+using System.IO;
+using System.Text;
+using System.Linq;
+using System.Collections.Generic;
+
+using MonkeyDoc;
+
+namespace MonkeyDoc.Generators
+{
+       /// <summary>
+       /// This generators returns the raw content of the HelpSource without any transformation
+       /// </summary>
+       public class RawGenerator : IDocGenerator<string>
+       {
+               public string Generate (HelpSource hs, string id)
+               {
+                       if (hs == null || string.IsNullOrEmpty (id))
+                               return null;
+
+                       IEnumerable<string> parts;
+                       if (hs.IsMultiPart (id, out parts))
+                               return GenerateMultiPart (hs, parts, id);
+
+                       if (hs.IsRawContent (id))
+                               return hs.GetText (id) ?? string.Empty;
+
+                       var result = hs.IsGeneratedContent (id) ? hs.GetCachedText (id) : new StreamReader (hs.GetCachedHelpStream (id)).ReadToEnd ();
+
+                       return result;
+               }
+
+               string GenerateMultiPart (HelpSource hs, IEnumerable<string> ids, string originalId)
+               {
+                       var sb = new StringBuilder ();
+                       foreach (var id in ids)
+                               sb.AppendLine (Generate (hs, id));
+                       return sb.ToString ();
+               }
+       }
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/generators/html/Addin2Html.cs b/mcs/tools/monkeydoc/MonkeyDoc/generators/html/Addin2Html.cs
new file mode 100644 (file)
index 0000000..3d37482
--- /dev/null
@@ -0,0 +1,197 @@
+using System;
+using System.IO;
+using System.Text;
+using System.Xml;
+using System.Xml.Xsl;
+using System.Xml.XPath;
+using System.Collections.Generic;
+
+namespace MonkeyDoc.Generators.Html
+{
+       public class Addin2Html : IHtmlExporter
+       {
+               public string CssCode {
+                       get {
+                               return string.Empty;
+                       }
+               }
+
+               public string Export (Stream stream, Dictionary<string, string> extraArgs)
+               {
+                       using (var reader = new StreamReader (stream))
+                               return Htmlize (GetAddin (reader, extraArgs["AddinID"]),
+                                               extraArgs["show"],
+                                               extraArgs["AddinID"],
+                                               extraArgs["FileID"],
+                                               extraArgs["NodeID"]);
+               }
+
+               public string Export (string input, Dictionary<string, string> extraArgs)
+               {
+                       return Htmlize (GetAddin (new StringReader (input), extraArgs["AddinID"]),
+                                       extraArgs["show"],
+                                       extraArgs["AddinID"],
+                                       extraArgs["FileID"],
+                                       extraArgs["NodeID"]);
+               }
+
+               XmlElement GetAddin (TextReader reader, string addinId)
+               {
+                       XmlDocument doc = new XmlDocument ();
+                       doc.Load (reader);
+                       XmlElement addin = (XmlElement) doc.SelectSingleNode ("Addins/Addin[@fullId='" + addinId + "']");
+                       return addin != null ? addin : null;
+               }
+
+               public string Htmlize (XmlElement addin, string urlType, string addinId, string fileId, string path)
+               {
+                       if (urlType == MonkeyDoc.Providers.AddinsHelpSource.AddinPrefix)
+                               return GetAddinTextFromUrl (addin, addinId, fileId);
+                       else if (urlType == MonkeyDoc.Providers.AddinsHelpSource.ExtensionPrefix)
+                               return GetExtensionTextFromUrl (addin, addinId, fileId, path);
+                       else if (urlType == MonkeyDoc.Providers.AddinsHelpSource.ExtensionNodePrefix)
+                               return GetExtensionNodeTextFromUrl (addin, addinId, fileId, path);
+
+                       return null;
+               }
+
+               protected string GetAddinTextFromUrl (XmlElement addin, string addinId, string fileId)
+               {
+                       if (addin == null)
+                               return "<html>Add-in not found: " + addinId + "</html>";
+                       
+                       StringBuilder sb = new StringBuilder ("<html>");
+                       sb.Append ("<h1>").Append (addin.GetAttribute ("name")).Append ("</h1>");
+                       XmlElement docs = (XmlElement) addin.SelectSingleNode ("Description");
+                       if (docs != null)
+                               sb.Append (docs.InnerText);
+
+                       sb.Append ("<p><table border=\"1\" cellpadding=\"4\" cellspacing=\"0\">");
+                       sb.AppendFormat ("<tr><td><b>Id</b></td><td>{0}</td></tr>", addin.GetAttribute ("addinId"));
+                       sb.AppendFormat ("<tr><td><b>Namespace</b></td><td>{0}</td></tr>", addin.GetAttribute ("namespace"));
+                       sb.AppendFormat ("<tr><td><b>Version</b></td><td>{0}</td></tr>", addin.GetAttribute ("version"));
+                       sb.Append ("</table></p>");
+                       sb.Append ("<p><b>Extension Points</b>:</p>");
+                       sb.Append ("<ul>");
+                       
+                       foreach (XmlElement ep in addin.SelectNodes ("ExtensionPoint")) {
+                               sb.AppendFormat ("<li><a href=\"extension-point:{0}#{1}#{2}\">{3}</li>", fileId, addinId, ep.GetAttribute ("path"), ep.GetAttribute ("name"));
+                       }
+                       sb.Append ("</ul>");
+                       
+                       sb.Append ("</html>");
+                       return sb.ToString ();
+               }
+               
+               protected string GetExtensionTextFromUrl (XmlElement addin, string addinId, string fileId, string path)
+               {
+                       if (addin == null)
+                               return "<html>Add-in not found: " + addinId + "</html>";
+                       
+                       XmlElement ext = (XmlElement) addin.SelectSingleNode ("ExtensionPoint[@path='" + path + "']");
+                       if (ext == null)
+                               return "<html>Extension point not found: " + path + "</html>";
+                       
+                       StringBuilder sb = new StringBuilder ("<html>");
+                       sb.Append ("<h1>").Append (ext.GetAttribute ("name")).Append ("</h1>");
+
+                       path = path.Replace ("/", " <b>/</b> ");
+                       sb.Append ("<p><b>Path</b>: ").Append (path).Append ("</p>");
+                       XmlElement desc = (XmlElement) ext.SelectSingleNode ("Description");
+                       if (desc != null)
+                               sb.Append (desc.InnerText);
+
+                       sb.Append ("<p><b>Extension Nodes</b>:</p>");
+                       sb.Append ("<table border=\"1\" cellpadding=\"4\" cellspacing=\"0\">");
+                       
+                       foreach (XmlElement en in ext.SelectNodes ("ExtensionNode")) {
+                               string nid = en.GetAttribute ("id");
+                               string nname = en.GetAttribute ("name"); 
+                               string sdesc = "";
+                               desc = (XmlElement) en.SelectSingleNode ("Description");
+                               if (desc != null)
+                                       sdesc = desc.InnerText;
+                               
+                               sb.AppendFormat ("<tr><td><a href=\"extension-node:{0}#{1}#{2}\">{3}</td><td>{4}</td></tr>", fileId, addinId, nid, nname, sdesc);
+                       }
+                       sb.Append ("</table>");
+                       
+                       sb.Append ("</html>");
+                       return sb.ToString ();
+               }
+               
+               protected string GetExtensionNodeTextFromUrl (XmlElement addin, string addinId, string fileId, string nodeId)
+               {
+                       if (addin == null)
+                               return "<html>Add-in not found: " + addinId + "</html>";
+                       
+                       XmlElement node = (XmlElement) addin.SelectSingleNode ("ExtensionNodeType[@id='" + nodeId + "']");
+                       if (node == null)
+                               return "<html>Extension point not found: " + nodeId + "</html>";
+                       
+                       StringBuilder sb = new StringBuilder ("<html>");
+                       sb.Append ("<h1>").Append (node.GetAttribute ("name")).Append ("</h1>");
+                       XmlElement desc = (XmlElement) node.SelectSingleNode ("Description");
+                       if (desc != null)
+                               sb.Append (desc.InnerText);
+
+                       sb.Append ("<p><b>Attributes</b>:</p>");
+                       sb.Append ("<table border=\"1\" cellpadding=\"4\" cellspacing=\"0\"><tr>");
+                       sb.Append ("<td><b>Name</b></td>");
+                       sb.Append ("<td><b>Type</b></td>");
+                       sb.Append ("<td><b>Required</b></td>");
+                       sb.Append ("<td><b>Localizable</b></td>");
+                       sb.Append ("<td><b>Description</b></td>");
+                       sb.Append ("<tr>");
+                       sb.Append ("<td>id</td>");
+                       sb.Append ("<td>System.String</td>");
+                       sb.Append ("<td></td>");
+                       sb.Append ("<td></td>");
+                       sb.Append ("<td>Identifier of the node.</td>");
+                       sb.Append ("</tr>");
+                       
+                       foreach (XmlElement at in node.SelectNodes ("Attributes/Attribute")) {
+                               sb.Append ("<tr>");
+                               sb.AppendFormat ("<td>{0}</td>", at.GetAttribute ("name"));
+                               sb.AppendFormat ("<td>{0}</td>", at.GetAttribute ("type"));
+                               if (at.GetAttribute ("required") == "True")
+                                       sb.Append ("<td>Yes</td>");
+                               else
+                                       sb.Append ("<td></td>");
+                               if (at.GetAttribute ("localizable") == "True")
+                                       sb.Append ("<td>Yes</td>");
+                               else
+                                       sb.Append ("<td></td>");
+                               string sdesc = "";
+                               desc = (XmlElement) at.SelectSingleNode ("Description");
+                               if (desc != null)
+                                       sdesc = desc.InnerText;
+                               
+                               sb.AppendFormat ("<td>{0}</td>", sdesc);
+                               sb.Append ("</tr>");
+                       }
+                       sb.Append ("</table>");
+
+                       XmlNodeList children = node.SelectNodes ("ChildNodes/ExtensionNode");
+                       if (children.Count > 0) {
+                               sb.Append ("<p><b>Child Nodes</b>:</p>");
+                               sb.Append ("<table border=\"1\" cellpadding=\"4\" cellspacing=\"0\">");
+                               
+                               foreach (XmlElement en in children) {
+                                       string nid = en.GetAttribute ("id");
+                                       string nname = en.GetAttribute ("name"); 
+                                       string sdesc = "";
+                                       desc = (XmlElement) en.SelectSingleNode ("Description");
+                                       if (desc != null)
+                                               sdesc = desc.InnerText;
+                                       
+                                       sb.AppendFormat ("<tr><td><a href=\"extension-node:{0}#{1}#{2}\">{3}</td><td>{4}</td></tr>", fileId, addinId, nid, nname, sdesc);
+                               }
+                               sb.Append ("</table>");
+                       }
+                       
+                       sb.Append ("</html>");
+                       return sb.ToString ();
+               }
+       }
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/generators/html/Ecma2Html.cs b/mcs/tools/monkeydoc/MonkeyDoc/generators/html/Ecma2Html.cs
new file mode 100644 (file)
index 0000000..ed329e3
--- /dev/null
@@ -0,0 +1,307 @@
+using System;
+using System.IO;
+using System.Text;
+using System.Linq;
+using System.Xml;
+using System.Xml.Xsl;
+using System.Xml.XPath;
+using System.Collections.Generic;
+
+using Mono.Documentation;
+using BF = System.Reflection.BindingFlags;
+
+namespace MonkeyDoc.Generators.Html
+{
+       public class Ecma2Html : IHtmlExporter
+       {
+               static string css_ecma;
+               static string js;
+               static XslCompiledTransform ecma_transform;
+               readonly ExtensionObject ExtObject = new ExtensionObject ();
+
+               public Ecma2Html ()
+               {
+               }
+
+               public string CssCode {
+                       get {
+                               if (css_ecma != null)
+                                       return css_ecma;
+                               var assembly = typeof(Ecma2Html).Assembly;
+                               Stream str_css = assembly.GetManifestResourceStream ("mono-ecma.css");
+                               css_ecma = (new StreamReader (str_css)).ReadToEnd();
+                               return css_ecma;
+                       }
+               }
+
+               public string JsCode {
+                       get {
+                               if (js != null)
+                                       return js;
+                               var assembly = typeof(Ecma2Html).Assembly;
+                               Stream str_js = assembly.GetManifestResourceStream ("helper.js");
+                               js = (new StreamReader (str_js)).ReadToEnd();
+                               return js;
+                       }
+               }
+               
+               public string Htmlize (XmlReader ecma_xml, Dictionary<string, string> extraArgs)
+               {
+                       var args = new XsltArgumentList ();
+                       args.AddExtensionObject("monodoc:///extensions", ExtObject);
+                       foreach (var kvp in extraArgs)
+                               args.AddParam (kvp.Key, string.Empty, kvp.Value);
+
+                       return Htmlize(ecma_xml, args);
+               }
+
+               public string Htmlize (XmlReader ecma_xml, XsltArgumentList args)
+               {
+                       EnsureTransform ();
+               
+                       var output = new StringBuilder ();
+                       ecma_transform.Transform (ecma_xml, 
+                                                 args, 
+                                                 XmlWriter.Create (output, ecma_transform.OutputSettings),
+                                                 CreateDocumentResolver ());
+                       return output.ToString ();
+               }
+               
+               protected virtual XmlResolver CreateDocumentResolver ()
+               {
+                       // results in using XmlUrlResolver
+                       return null;
+               }
+
+               public string Export (Stream stream, Dictionary<string, string> extraArgs)
+               {
+                       return Htmlize (XmlReader.Create (stream), extraArgs);
+               }
+
+               public string Export (string input, Dictionary<string, string> extraArgs)
+               {
+                       return Htmlize (XmlReader.Create (new StringReader (input)), extraArgs);
+               }
+               
+               static void EnsureTransform ()
+               {
+                       if (ecma_transform == null) {
+                               ecma_transform = new XslCompiledTransform ();
+                               var assembly = System.Reflection.Assembly.GetCallingAssembly ();
+                       
+                               Stream stream = assembly.GetManifestResourceStream ("mono-ecma-css.xsl");
+                               XmlReader xml_reader = new XmlTextReader (stream);
+                               XmlResolver r = new ManifestResourceResolver (".");
+                               ecma_transform.Load (xml_reader, XsltSettings.TrustedXslt, r);                  
+                       }
+               }
+
+               public class ExtensionObject
+               {
+                       bool quiet = true;
+
+                       public string Colorize(string code, string lang)
+                       {
+                               return Mono.Utilities.Colorizer.Colorize(code,lang);
+                       }
+
+                       // Used by stylesheet to nicely reformat the <see cref=> tags. 
+                       public string MakeNiceSignature(string sig, string contexttype)
+                       {
+                               if (sig.Length < 3)
+                                       return sig;
+                               if (sig[1] != ':')
+                                       return sig;
+
+                               char s = sig[0];
+                               sig = sig.Substring(2);
+                       
+                               switch (s) {
+                               case 'N': return sig;
+                               case 'T': return ShortTypeName (sig, contexttype);
+
+                               case 'C': case 'M': case 'P': case 'F': case 'E':
+                                       string type, mem, arg;
+                                       
+                                       // Get arguments
+                                       int paren;
+                                       if (s == 'C' || s == 'M')
+                                               paren = sig.IndexOf("(");
+                                       else if (s == 'P')
+                                               paren = sig.IndexOf("[");
+                                       else
+                                               paren = 0;
+                                       
+                                       if (paren > 0 && paren < sig.Length-1) {
+                                               string[] args = sig.Substring(paren+1, sig.Length-paren-2).Split(',');                                          
+                                               for (int i = 0; i < args.Length; i++)
+                                                       args[i] = ShortTypeName(args[i], contexttype);
+                                               arg = "(" + String.Join(", ", args) + ")";
+                                               sig = sig.Substring(0, paren); 
+                                       } else {
+                                               arg = string.Empty;
+                                       }
+
+                                       // Get type and member names
+                                       int dot = sig.LastIndexOf(".");
+                                       if (s == 'C' || dot <= 0 || dot == sig.Length-1) {
+                                               mem = string.Empty;
+                                               type = sig;
+                                       } else {
+                                               type = sig.Substring(0, dot);
+                                               mem = sig.Substring(dot);
+                                       }
+                                               
+                                       type = ShortTypeName(type, contexttype);
+                                       
+                                       return type + mem + arg;
+
+                               default:
+                                       return sig;
+                               }
+                       }
+
+                       static string ShortTypeName(string name, string contexttype)
+                       {
+                               int dot = contexttype.LastIndexOf(".");
+                               if (dot < 0) return name;
+                               string contextns = contexttype.Substring(0, dot+1);
+
+                               if (name == contexttype)
+                                       return name.Substring(dot+1);
+                       
+                               if (name.StartsWith(contextns))
+                                       return name.Substring(contextns.Length);
+                       
+                               return name.Replace("+", ".");
+                       }
+
+                       string MonoImpInfo(string assemblyname, string typename, string membername, string arglist, bool strlong)
+                       {
+                               if (quiet)
+                                       return string.Empty;
+                               
+                               var a = new List<string> ();
+                               if (!string.IsNullOrEmpty (arglist)) a.Add (arglist);
+                               return MonoImpInfo(assemblyname, typename, membername, a, strlong);
+                       }
+
+                       string MonoImpInfo(string assemblyname, string typename, string membername, XPathNodeIterator itr, bool strlong)
+                       {
+                               if (quiet)
+                                       return string.Empty;
+                               
+                               var rgs = itr.Cast<XPathNavigator> ().Select (nav => nav.Value).ToList ();
+                       
+                               return MonoImpInfo (assemblyname, typename, membername, rgs, strlong);
+                       }
+               
+                       string MonoImpInfo(string assemblyname, string typename, string membername, List<string> arglist, bool strlong)
+                       {
+                               try {
+                                       System.Reflection.Assembly assembly = null;
+                               
+                                       try {
+                                               assembly = System.Reflection.Assembly.LoadWithPartialName(assemblyname);
+                                       } catch (Exception) {
+                                               // nothing.
+                                       }
+                               
+                                       if (assembly == null) {
+                                               /*if (strlong) return "The assembly " + assemblyname + " is not available to MonoDoc.";
+                                                 else return string.Empty;*/
+                                               return string.Empty; // silently ignore
+                                       }
+
+                                       Type t = assembly.GetType(typename, false);
+                                       if (t == null) {
+                                               if (strlong)
+                                                       return typename + " has not been implemented.";
+                                               else
+                                                       return "Not implemented.";
+                                       }
+
+                                       // The following code is flakey and fails to find existing members
+                                       return string.Empty;
+                               } catch (Exception) {
+                                       return string.Empty;
+                               }
+                       }
+               
+                       string MonoImpInfo(System.Reflection.MemberInfo mi, string itemtype, bool strlong)
+                       {
+                               if (quiet)
+                                       return string.Empty;
+                               
+                               string s = string.Empty;
+
+                               object[] atts = mi.GetCustomAttributes(true);
+                               int todoctr = 0;
+                               foreach (object att in atts) if (att.GetType().Name == "MonoTODOAttribute") todoctr++;
+
+                               if (todoctr > 0) {
+                                       if (strlong)
+                                               s = "This " + itemtype + " is marked as being unfinished.<BR/>\n";
+                                       else 
+                                               s = "Unfinished.";
+                               }
+
+                               return s;
+                       }
+
+                       public string MonoImpInfo(string assemblyname, string typename, bool strlong)
+                       {
+                               if (quiet)
+                                       return string.Empty;
+                               
+                               try {
+                                       if (assemblyname == string.Empty)
+                                               return string.Empty;
+
+                                       var assembly = System.Reflection.Assembly.LoadWithPartialName(assemblyname);
+                                       if (assembly == null)
+                                               return string.Empty;
+
+                                       Type t = assembly.GetType(typename, false);
+                                       if (t == null) {
+                                               if (strlong)
+                                                       return typename + " has not been implemented.";
+                                               else
+                                                       return "Not implemented.";
+                                       }
+
+                                       string s = MonoImpInfo(t, "type", strlong);
+
+                                       if (strlong) {
+                                               var mis = t.GetMembers (BF.Static | BF.Instance | BF.Public | BF.NonPublic);
+
+                                               // Scan members for MonoTODO attributes
+                                               int mctr = 0;
+                                               foreach (var mi in mis) {
+                                                       string mii = MonoImpInfo(mi, null, false);
+                                                       if (mii != string.Empty) mctr++; 
+                                               }
+                                               if (mctr > 0) {
+                                                       s += "This type has " + mctr + " members that are marked as unfinished.<BR/>";
+                                               }
+                                       }
+
+                                       return s;
+
+                               } catch (Exception) {
+                                       return string.Empty;
+                               }                       
+                       }
+
+                       public bool MonoEditing ()
+                       {
+                               return false;
+                       }
+               
+                       public bool IsToBeAdded(string text)
+                       {
+                               return text.StartsWith ("To be added");
+                       }
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/generators/html/Ecmaspec2Html.cs b/mcs/tools/monkeydoc/MonkeyDoc/generators/html/Ecmaspec2Html.cs
new file mode 100644 (file)
index 0000000..95f4064
--- /dev/null
@@ -0,0 +1,66 @@
+using System;
+using System.IO;
+using System.Xml;
+using System.Xml.Xsl;
+using System.Xml.XPath;
+using System.Collections.Generic;
+
+namespace MonkeyDoc.Generators.Html
+{
+       public class Ecmaspec2Html : IHtmlExporter
+       {
+               static string css_ecmaspec;
+               static XslTransform ecma_transform;
+               static XsltArgumentList args = new XsltArgumentList();
+
+               public string CssCode {
+                       get {
+                               if (css_ecmaspec != null)
+                                       return css_ecmaspec;
+                               System.Reflection.Assembly assembly = System.Reflection.Assembly.GetCallingAssembly ();
+                               Stream str_css = assembly.GetManifestResourceStream ("ecmaspec.css");
+                               css_ecmaspec = (new StreamReader (str_css)).ReadToEnd ();
+                               return css_ecmaspec;
+                       }
+               }
+
+               class ExtObj
+               {
+                       public string Colorize (string code, string lang)
+                       {
+                               return Mono.Utilities.Colorizer.Colorize (code, lang);
+                       }
+               }
+
+               public string Export (Stream stream, Dictionary<string, string> extraArgs)
+               {
+                       return Htmlize (new XPathDocument (stream));
+               }
+
+               public string Export (string input, Dictionary<string, string> extraArgs)
+               {
+                       return Htmlize (new XPathDocument (new StringReader (input)));
+               }
+
+               static string Htmlize (XPathDocument ecma_xml)
+               {
+                       if (ecma_transform == null){
+                               ecma_transform = new XslTransform ();
+                               System.Reflection.Assembly assembly = System.Reflection.Assembly.GetCallingAssembly ();
+                               Stream stream;
+                               stream = assembly.GetManifestResourceStream ("ecmaspec-html-css.xsl");
+
+                               XmlReader xml_reader = new XmlTextReader (stream);
+                               ecma_transform.Load (xml_reader, null, null);
+                               args.AddExtensionObject ("monodoc:///extensions", new ExtObj ()); 
+                       }
+               
+                       if (ecma_xml == null) return "";
+
+                       StringWriter output = new StringWriter ();
+                       ecma_transform.Transform (ecma_xml, args, output, null);
+               
+                       return output.ToString ();
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/generators/html/Error2Html.cs b/mcs/tools/monkeydoc/MonkeyDoc/generators/html/Error2Html.cs
new file mode 100644 (file)
index 0000000..167d1f5
--- /dev/null
@@ -0,0 +1,110 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using System.Xml.XPath;
+using System.Collections.Generic;
+
+namespace MonkeyDoc.Generators.Html
+{
+       public class Error2Html : IHtmlExporter
+       {
+               public string Export (string input, Dictionary<string, string> extraArgs)
+               {
+                       return Htmlize (new XPathDocument (new StringReader (input)));
+               }
+
+               public string Export (Stream input, Dictionary<string, string> extraArgs)
+               {
+                       return Htmlize (new XPathDocument (input));
+               }
+
+               public string CssCode {
+                       get {
+                               return @"
+                                        #error_ref { 
+                                           background: #debcb0; 
+                                           border: 2px solid #782609; 
+                                        }
+                                        div.summary {
+                                                font-size: 110%;
+                                                font-weight: bolder;
+                                        }
+                                        div.details {
+                                                font-size: 110%;
+                                                font-weight: bolder;
+                                        }
+                                        div.code_example {
+                                               background: #f5f5dd;
+                                               border: 1px solid black;
+                                               padding-left: 1em;
+                                               padding-bottom: 1em;
+                                               margin-top: 1em;
+                                               white-space: pre;
+                                               margin-bottom: 1em;
+                                        }
+                                        div.code_ex_title {
+                                               position: relative;
+                                               top: -1em;
+                                               left: 30%;
+                                               background: #cdcd82;
+                                               border: 1px solid black;
+                                               color: black;
+                                               font-size: 65%;
+                                               text-transform: uppercase;
+                                               width: 40%;
+                                               padding: 0.3em;
+                                               text-align: center;
+                                        }";
+                       }
+               }
+
+               public string Htmlize (IXPathNavigable doc)
+               {
+                       var navigator = doc.CreateNavigator ();
+                       var errorName = navigator.SelectSingleNode ("//ErrorDocumentation/ErrorName");
+                       var details = navigator.SelectSingleNode ("//ErrorDocumentation/Details");
+
+                       StringWriter sw = new StringWriter ();
+                       XmlWriter w = new XmlTextWriter (sw);
+                       
+                       WriteElementWithClass (w, "div", "header");
+                       w.WriteAttributeString ("id", "error_ref");
+                       WriteElementWithClass (w, "div", "subtitle", "Compiler Error Reference");
+                       WriteElementWithClass (w, "div", "title", "Error " + (errorName == null ? string.Empty : errorName.Value));
+                       w.WriteEndElement ();
+
+                       if (details != null) {
+                               WriteElementWithClass (w, "div", "summary", "Summary");
+
+                               var summary = details.SelectSingleNode ("/Summary");
+                               w.WriteValue (summary == null ? string.Empty : summary.Value);
+                               
+                               WriteElementWithClass (w, "div", "details", "Details");
+                               var de = details.SelectSingleNode ("/Details");
+                               w.WriteValue (de == null ? string.Empty : de.Value);
+                       }
+                       
+                       foreach (XPathNavigator xmp in navigator.Select ("//ErrorDocumentation/Examples/string")) {
+                               WriteElementWithClass (w, "div", "code_example");
+                               WriteElementWithClass (w, "div", "code_ex_title", "Example");
+                               w.WriteRaw (Mono.Utilities.Colorizer.Colorize (xmp.Value, "c#"));;
+                               w.WriteEndElement ();
+                       }
+                       
+                       w.Close ();
+                       
+                       return sw.ToString ();
+               }
+
+               void WriteElementWithClass (XmlWriter w, string element, string cls, string content = null)
+               {
+                       w.WriteStartElement (element);
+                       w.WriteAttributeString ("class", cls);
+                       if (!string.IsNullOrEmpty (content)) {
+                               w.WriteValue (content);
+                               w.WriteEndElement ();
+                       }
+               }
+       }
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/generators/html/Idem.cs b/mcs/tools/monkeydoc/MonkeyDoc/generators/html/Idem.cs
new file mode 100644 (file)
index 0000000..0a58b21
--- /dev/null
@@ -0,0 +1,34 @@
+using System;
+using System.IO;
+using System.Text;
+using System.Collections.Generic;
+
+using MonkeyDoc;
+using MonkeyDoc.Generators;
+
+namespace MonkeyDoc.Generators.Html
+{
+       // Input is expected to be already HTML so just return it
+       public class Idem : IHtmlExporter
+       {
+               public string CssCode {
+                       get {
+                               return string.Empty;
+                       }
+               }
+
+               public string Export (Stream input, Dictionary<string, string> extraArgs)
+               {
+                       if (input == null)
+                               return null;
+                       return new StreamReader (input).ReadToEnd ();
+               }
+
+               public string Export (string input, Dictionary<string, string> extraArgs)
+               {
+                       if (string.IsNullOrEmpty (input))
+                               return null;
+                       return input;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/generators/html/Man2Html.cs b/mcs/tools/monkeydoc/MonkeyDoc/generators/html/Man2Html.cs
new file mode 100644 (file)
index 0000000..68ed5ed
--- /dev/null
@@ -0,0 +1,316 @@
+using System;
+using System.IO;
+using System.Text;
+using System.Collections.Generic;
+
+using MonkeyDoc;
+using MonkeyDoc.Generators;
+
+namespace MonkeyDoc.Generators.Html
+{
+       public class Man2Html : IHtmlExporter
+       {
+               public string CssCode {
+                       get {
+                               return string.Empty;
+                       }
+               }
+
+               public string Export (Stream input, Dictionary<string, string> extraArgs)
+               {
+                       if (input == null)
+                               return null;
+                       return GetTextFromReader (new StreamReader (input));
+               }
+
+               public string Export (string input, Dictionary<string, string> extraArgs)
+               {
+                       if (string.IsNullOrEmpty (input))
+                               return null;
+                       return GetTextFromReader (new StringReader (input));
+               }
+
+               public static string GetTextFromReader (TextReader file)
+               {
+                       string line;
+                       StateInfo s = new StateInfo ();
+
+                       while ((line = file.ReadLine ()) != null)
+                               ProcessLine (line, s);
+
+                       return s.output.ToString ();
+               }
+
+               enum ListState {
+                       None,
+                       Start,
+                       Title,
+               }
+
+               class StateInfo {
+                       public ListState ls;
+                       public Stack<string> tags = new Stack<string> ();
+                       public StringBuilder output = new StringBuilder ();
+               }
+
+               static void ProcessLine (string line, StateInfo s)
+               {
+                       string[] parts = SplitLine (line);
+                       switch (parts [0]) {
+                       case ".\\\"": // comments
+                       case ".de":   // define macro
+                       case ".if":   // if
+                       case ".ne":   // ???
+                       case "..":    // end macro
+                               // ignore
+                               break;
+                       case ".I":
+                               s.output.Append ("<i>");
+                               Translate (parts, 1, s.output);
+                               s.output.Append ("</i>");
+                               break;
+                       case ".B":
+                               s.output.Append ("<b>");
+                               Translate (parts, 1, s.output);
+                               s.output.Append ("</b>");
+                               break;
+                       case ".br":
+                               Translate (parts, 1, s.output);
+                               s.output.Append ("<br />");
+                               break;
+                       case ".nf":
+                               Expect (s, "</p>");
+                               s.output.Append ("<pre>\n");
+                               s.tags.Push ("</pre>");
+                               break;
+                       case ".fi":
+                               Expect (s, "</pre>");
+                               break;
+                       case ".PP":
+                               Expect (s, "</p>", "</dd>", "</dl>");
+                               goto case ".Sp";
+                       case ".Sp":
+                               Expect (s, "</p>");
+                               s.output.Append ("<p>");
+                               Translate (parts, 1, s.output);
+                               s.tags.Push ("</p>");
+                               break;
+                       case ".RS":
+                               Expect (s, "</p>");
+                               s.output.Append ("<blockquote>");
+                               s.tags.Push ("</blockquote>");
+                               break;
+                       case ".RE":
+                               ClearUntil (s, "</blockquote>");
+                               break;
+                       case ".SH":
+                               ClearAll (s);
+                               s.output.Append ("<h2>");
+                               Translate (parts, 1, s.output);
+                               s.output.Append ("</h2>")
+                                       .Append ("<blockquote>");
+                               s.tags.Push ("</blockquote>");
+                               break;
+                       case ".SS":
+                               s.output.Append ("<h3>");
+                               Translate (parts, 1, s.output);
+                               s.output.Append ("</h3>");
+                               break;
+                       case ".TH": {
+                               ClearAll (s);
+                               string name = "", extra = "";
+                               if (parts.Length >= 4 && parts [2].Trim ().Length == 0) {
+                                       name = parts [1] + "(" + parts [3] + ")";
+                                       if (parts.Length > 4) {
+                                               int start = 4;
+                                               if (parts [start].Trim ().Length == 0)
+                                                       ++start;
+                                               extra = string.Join ("", parts, start, parts.Length-start);
+                                       }
+                               }
+                               else
+                                       name = string.Join ("", parts, 1, parts.Length-1);
+                               s.output.Append ("<table width=\"100%\" bgcolor=\"#b0c4da\">" + 
+                                                "<tr colspan=\"2\"><td>Manual Pages</td></tr>\n" +
+                                                "<tr><td><h3>");
+                               Translate (name, s.output);
+                               s.output.Append ("</h3></td><td align=\"right\">");
+                               Translate (extra, s.output);
+                               s.output.Append ("</td></tr></table>");
+                               break;
+                       }
+                       case ".TP":
+                               Expect (s, "</p>");
+                               if (s.tags.Count > 0 && s.tags.Peek ().ToString () != "</dd>") {
+                                       s.output.Append ("<dl>");
+                                       s.tags.Push ("</dl>");
+                               }
+                               else
+                                       Expect (s, "</dd>");
+                               s.output.Append ("<dt>");
+                               s.tags.Push ("</dt>");
+                               s.ls = ListState.Start;
+                               break;
+                       default:
+                               Translate (line, s.output);
+                               break;
+                       }
+                       if (s.ls == ListState.Start)
+                               s.ls = ListState.Title;
+                       else if (s.ls == ListState.Title) {
+                               Expect (s, "</dt>");
+                               s.output.Append ("<dd>");
+                               s.tags.Push ("</dd>");
+                               s.ls = ListState.None;
+                       }
+                       s.output.Append ("\n");
+               }
+
+               static string[] SplitLine (string line)
+               {
+                       if (line.Length > 1 && line [0] != '.')
+                               return new string[]{null, line};
+
+                       int i;
+                       for (i = 0; i < line.Length; ++i) {
+                               if (char.IsWhiteSpace (line, i))
+                                       break;
+                       }
+
+                       if (i == line.Length)
+                               return new string[]{line};
+
+                       var pieces = new List<string> ();
+                       pieces.Add (line.Substring (0, i));
+                       bool inQuotes = false;
+                       bool prevWs   = true;
+                       ++i;
+                       int start = i;
+                       for ( ; i < line.Length; ++i) {
+                               char c = line [i];
+                               if (inQuotes) {
+                                       if (c == '"') {
+                                               Add (pieces, line, start, i);
+                                               start = i+1;
+                                               inQuotes = false;
+                                       }
+                               }
+                               else {
+                                       if (prevWs && c == '"') {
+                                               Add (pieces, line, start, i);
+                                               start = i+1;
+                                               inQuotes = true;
+                                       }
+                                       else if (char.IsWhiteSpace (c)) {
+                                               if (!prevWs) {
+                                                       Add (pieces, line, start, i);
+                                                       start = i;
+                                               }
+                                               prevWs = true;
+                                       }
+                                       else {
+                                               if (prevWs) {
+                                                       Add (pieces, line, start, i);
+                                                       start = i;
+                                               }
+                                               prevWs = false;
+                                       }
+                               }
+                       }
+                       if (start > 0 && start != line.Length)
+                               pieces.Add (line.Substring (start, line.Length-start));
+                       return pieces.ToArray ();
+               }
+
+               static void Add (List<string> pieces, string line, int start, int end)
+               {
+                       if (start == end)
+                               return;
+                       pieces.Add (line.Substring (start, end-start));
+               }
+
+               static void Expect (StateInfo s, params string[] expected)
+               {
+                       string e;
+                       while (s.tags.Count > 0 && 
+                              Array.IndexOf (expected, (e = s.tags.Peek ().ToString ())) >= 0) {
+                               s.output.Append (s.tags.Pop ().ToString ());
+                       }
+               }
+
+               static void ClearUntil (StateInfo s, string required)
+               {
+                       string e;
+                       while (s.tags.Count > 0 && 
+                              (e = s.tags.Peek ().ToString ()) != required) {
+                               s.output.Append (s.tags.Pop ().ToString ());
+                       }
+                       if (e == required)
+                               s.output.Append (s.tags.Pop ().ToString ());
+               }
+
+               static void ClearAll (StateInfo s)
+               {
+                       while (s.tags.Count > 0)
+                               s.output.Append (s.tags.Pop ().ToString ());
+               }
+
+               static void Translate (string[] lines, int startIndex, StringBuilder output)
+               {
+                       if (lines.Length <= startIndex)
+                               return;
+                       do {
+                               Translate (lines [startIndex++], output);
+                               if (startIndex == lines.Length)
+                                       break;
+                       } while (startIndex < lines.Length);
+               }
+
+               static void Translate (string line, StringBuilder output)
+               {
+                       string span = null;
+                       int start = output.Length;
+                       for (int i = 0; i < line.Length; ++i) {
+                               switch (line [i]) {
+                               case '\\': {
+                                       if ((i+2) < line.Length && line [i+1] == 'f') {
+                                               if (line [i+2] == 'I') {
+                                                       output.Append ("<i>");
+                                                       span = "</i>";
+                                               }
+                                               else if (line [i+2] == 'B') {
+                                                       output.Append ("<b>");
+                                                       span = "</b>";
+                                               }
+                                               else if (line [i+2] == 'R' || line [i+2] == 'P') {
+                                                       output.Append (span);
+                                               }
+                                               else
+                                                       goto default;
+                                               i += 2;
+                                       }
+                                       else if ((i+1) < line.Length) {
+                                               output.Append (line [i+1]);
+                                               ++i;
+                                       }
+                                       else
+                                               goto default;
+                                       break;
+                               }
+                               case '<':
+                                       output.Append ("&lt;");
+                                       break;
+                               case '>':
+                                       output.Append ("&gt;");
+                                       break;
+                               case '&':
+                                       output.Append ("&amp;");
+                                       break;
+                               default:
+                                       output.Append (line [i]);
+                                       break;
+                               }
+                       }
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/generators/html/MonoBook2Html.cs b/mcs/tools/monkeydoc/MonkeyDoc/generators/html/MonoBook2Html.cs
new file mode 100644 (file)
index 0000000..89a531c
--- /dev/null
@@ -0,0 +1,87 @@
+using System;
+using System.IO;
+using System.Text;
+using System.Xml;
+using System.Collections.Generic;
+
+using MonkeyDoc;
+using MonkeyDoc.Generators;
+
+namespace MonkeyDoc.Generators.Html
+{
+       // Input is expected to be already HTML so just return it
+       public class MonoBook2Html : IHtmlExporter
+       {
+               public string CssCode {
+                       get {
+                               return @"   h3 { 
+       font-size: 18px;
+       padding-bottom: 4pt;
+       border-bottom: 2px solid #dddddd;
+   }
+       
+   .api {
+     border: 1px solid;
+     padding: 10pt;
+     margin: 10pt;
+   } 
+
+   .api-entry { 
+       border-bottom: none;
+       font-size: 18px;
+   }
+
+   .prototype {
+     border: 1px solid;
+     background-color: #f2f2f2;
+     padding: 5pt;
+     margin-top: 5pt;
+     margin-bottom: 5pt;  
+   } 
+
+   .header {
+     border: 1px solid !important;
+     padding: 0 0 5pt 5pt !important;
+     margin: 10pt !important;
+     white-space: pre !important;
+       font-family: monospace !important;
+     font-weight: normal !important;
+     font-size: 1em !important;
+   }
+    
+   .code {
+     border: 1px solid;
+     padding: 0 0 5pt 5pt;
+     margin: 10pt;
+     white-space: pre;
+       font-family: monospace;
+   }
+";
+                       }
+               }
+
+               public string Export (Stream input, Dictionary<string, string> extraArgs)
+               {
+                       if (input == null)
+                               return null;
+                       return FromXmlReader (XmlReader.Create (input));
+               }
+
+               public string Export (string input, Dictionary<string, string> extraArgs)
+               {
+                       if (string.IsNullOrEmpty (input))
+                               return null;
+                       return FromXmlReader (XmlReader.Create (new StringReader (input)));
+               }
+
+               public string FromXmlReader (XmlReader reader)
+               {
+                       if (!reader.ReadToDescendant ("head"))
+                               return null;
+                       if (!reader.ReadToNextSibling ("body"))
+                               return null;
+
+                       return reader.ReadInnerXml ();
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/generators/html/Toc2Html.cs b/mcs/tools/monkeydoc/MonkeyDoc/generators/html/Toc2Html.cs
new file mode 100644 (file)
index 0000000..eef17c2
--- /dev/null
@@ -0,0 +1,44 @@
+using System;
+using System.IO;
+using System.Xml;
+using System.Xml.Xsl;
+using System.Xml.XPath;
+using System.Reflection;
+using System.Collections.Generic;
+
+namespace MonkeyDoc.Generators.Html
+{
+       public class Toc2Html : IHtmlExporter
+       {
+               XslTransform transform;
+
+               public Toc2Html ()
+               {
+                       transform = new XslTransform ();
+                       var assembly = Assembly.GetCallingAssembly ();
+                       var stream = assembly.GetManifestResourceStream ("toc-html.xsl");
+                       XmlReader xml_reader = new XmlTextReader (stream);
+                       transform.Load (xml_reader, null, null);
+               }
+
+               public string Export (Stream input, Dictionary<string, string> extraArgs)
+               {
+                       var output = new StringWriter ();
+                       transform.Transform (new XPathDocument (input), null, output, null);
+                       return output.ToString ();
+               }
+
+               public string Export (string input, Dictionary<string, string> extraArgs)
+               {
+                       var output = new StringWriter ();
+                       transform.Transform (new XPathDocument (new StringReader (input)), null, output, null);
+                       return output.ToString ();
+               }
+
+               public string CssCode {
+                       get {
+                               return string.Empty;
+                       }
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/index.cs b/mcs/tools/monkeydoc/MonkeyDoc/index.cs
new file mode 100644 (file)
index 0000000..b365b9e
--- /dev/null
@@ -0,0 +1,310 @@
+//
+// index.cs: Handling of the index files
+//
+// Author:
+//   Miguel de Icaza (miguel@xamarin.com)
+//
+// (C) 2003 Ximian, Inc.
+// Copyright 2003-2011 Novell Inc
+// Copyright 2011 Xamarin Inc.
+//
+// Possible file format optimizations:
+//   * Do not use 4 bytes for each index entry, use 3 bytes
+//   * Find a way of compressing strings, there are plenty of duplicates
+//     Find common roots, and use an encoding that uses a root to compress data.
+//     "System", "System.Data", "System.Data class"
+//     0: PLAIN: "System"
+//     1: PLAIN: " class"
+//     2: LINK0 PLAIN ".DATA"
+//     3: LINK0 LINK1
+//     
+//     Maybe split everything at spaces and dots, and encode that:
+//     string-1-idx "System."
+//     string-1-idx "Data"
+//     2-items [ string-1-idx string-2-idx]
+//
+//     Other variations are possible;  Like Archive "System", "System." when we
+//     see "System.Data".
+//
+//
+
+using System;
+using System.IO;
+using System.Text;
+using System.Collections.Generic;
+
+namespace MonkeyDoc
+{
+       public class Topic
+       {
+               public readonly string Caption;
+               public readonly string SortKey;
+               public readonly string Url;
+
+               public Topic (string caption, string sort_key, string url)
+               {
+                       Caption = caption;
+                       SortKey = sort_key;
+                       Url = url;
+               }
+       }
+
+       public class IndexEntry
+       {
+               List<Topic> topics;
+
+               public int Position {
+                       get;
+                       private set;
+               }
+
+               public IList<Topic> Topics {
+                       get {
+                               return topics.AsReadOnly ();
+                       }
+               }
+
+               public int Count {
+                       get;
+                       private set;
+               }
+               
+               public void Add (Topic t)
+               {
+                       Count++;
+                       topics.Add (t);
+               }
+
+               public Topic this [int idx] {
+                       get {
+                               if (idx < 0 || idx > topics.Count)
+                                       throw new ArgumentOutOfRangeException ("idx");
+                               return topics[idx];
+                       }
+               }
+
+               //
+               // Constructor from a stream
+               //
+               public IndexEntry (FileStream fs, BinaryReader reader, int position)
+               {
+                       Count = reader.ReadInt32 ();
+                       int caption_offset = reader.ReadInt32 ();
+                       string caption;
+                       topics = new List<Topic> (Count);
+
+                       int [] offsets = new int [Count];
+                       for (int i = 0; i < Count; i++)
+                               offsets [i] = reader.ReadInt32 ();
+
+                       fs.Position = caption_offset;
+                       caption = reader.ReadString ();
+                       for (int i = 0; i < Count; i++){
+                               fs.Position = offsets [i];
+                               string url = reader.ReadString ();
+                               topics.Add (new Topic (caption, string.Empty, url));
+                       }
+               }
+
+               //
+               // Regular constructor
+       
+               public IndexEntry ()
+               {
+                       topics = new List<Topic> ();
+               }
+
+               public void WriteTopics (IndexMaker maker, Stream stream, BinaryWriter writer)
+               {
+                       //
+                       // Convention: entries with the same SortKey should have the same Caption
+                       //
+                       Position = (int) stream.Position;
+                       writer.Write (Count);
+
+                       if (Count == 0)
+                               return;
+
+                       writer.Write (maker.GetCode (topics[0].Caption));
+                       foreach (Topic t in topics)
+                               writer.Write (maker.GetCode (t.Url));
+               }
+       }
+
+       public class IndexMaker
+       {
+               Dictionary<string, IndexEntry> entries = new Dictionary<string, IndexEntry> ();
+               Dictionary<string, int> all_strings = new Dictionary<string, int> ();
+               int index_position;
+
+               void AddString (string str)
+               {
+                       if (!all_strings.ContainsKey (str))
+                               all_strings.Add (str, 0);
+               }
+
+               public void AddTopic (Topic topic)
+               {
+                       IndexEntry entry;
+                       if (!entries.TryGetValue (topic.SortKey, out entry)) {
+                               entry = new IndexEntry ();
+                               entries[topic.SortKey] = entry;
+                       }
+
+                       AddString (topic.SortKey);
+                       AddString (topic.Caption);
+                       AddString (topic.Url);
+                       entry.Add (topic);
+               }
+
+               public void Add (string caption, string sort_key, string url)
+               {
+                       Topic t = new Topic (caption, sort_key, url);
+                       AddTopic (t);
+               }
+       
+               void SaveStringTable (Stream stream, BinaryWriter writer)
+               {
+                       var keys = new List<string> (all_strings.Keys);
+                       foreach (string s in keys) {
+                               int pos = (int) stream.Position;
+                               writer.Write (s);
+                               all_strings [s] = pos;
+                       }
+               }
+
+               public int GetCode (string s)
+               {
+                       return all_strings [s];
+               }
+
+               void SaveTopics (Stream stream, BinaryWriter writer)
+               {
+                       //
+                       // Convention: entries with the same SortKey should have the same Caption
+                       //
+                       foreach (IndexEntry e in entries.Values)
+                               e.WriteTopics (this, stream, writer);
+               }
+
+               void SaveIndexEntries (Stream stream, BinaryWriter writer)
+               {
+                       index_position = (int) stream.Position;
+                       writer.Write (entries.Count);
+                       var keys = new List<string> (entries.Keys);
+                       keys.Sort (StringComparer.OrdinalIgnoreCase);
+               
+                       foreach (string s in keys){
+                               IndexEntry e = entries [s];
+                               writer.Write (e.Position);
+                       }
+               }
+
+               public void Save (string filename)
+               {
+                       Encoding utf8 = new UTF8Encoding (false, true);
+
+                       using (FileStream fs = File.OpenWrite (filename)){
+                               BinaryWriter writer = new BinaryWriter (fs, utf8);
+                               writer.Write (new byte [] { (byte) 'M', 
+                                                           (byte) 'o', (byte) 'i', 
+                                                           (byte) 'x'});
+
+                               // Leave room for pointer
+                               fs.Position = 8;
+
+                               SaveStringTable (fs, writer);
+                               SaveTopics (fs, writer);
+
+                               // index_position is set here
+                       
+                               SaveIndexEntries (fs, writer);
+
+                               fs.Position = 4;
+                               writer.Write (index_position);
+                       }
+               }
+       }
+
+       public interface IListModel
+       {
+               int Rows { get; }
+               string GetValue (int row);
+               string GetDescription (int row);
+       }
+
+       public class IndexReader : IListModel
+       {
+               Encoding utf8 = new UTF8Encoding (false, true);
+               FileStream fs;
+               BinaryReader reader;
+
+               // The offset of the table of entries
+               int table_offset;
+               int entries;
+
+               static public IndexReader Load (string filename)
+               {
+                       if (!File.Exists (filename))
+                               return null;
+
+                       try {
+                               return new IndexReader (filename);
+                       } catch {
+                               return null;
+                       }
+               }
+       
+               IndexReader (string filename)
+               {
+                       fs = File.OpenRead (filename);
+                       reader = new BinaryReader (fs, utf8);
+
+                       if (fs.ReadByte () != 'M' ||
+                           fs.ReadByte () != 'o' ||
+                           fs.ReadByte () != 'i' ||
+                           fs.ReadByte () != 'x'){
+                               throw new Exception ("Corrupt index");
+                       }
+
+                       // Seek to index_entries
+                       fs.Position = reader.ReadInt32 ();
+               
+                       entries = reader.ReadInt32 ();
+
+                       table_offset = (int) fs.Position;
+               }
+
+               public int Rows {
+                       get {
+                               return entries;
+                       }
+               }
+
+               public string GetValue (int row)
+               {
+                       fs.Position = row * 4 + table_offset;
+                       fs.Position = reader.ReadInt32 () + 4;
+                       int code = reader.ReadInt32 ();
+                       fs.Position = code;
+                       string caption = reader.ReadString ();
+
+                       return caption;
+               }
+
+               public string GetDescription (int row)
+               {
+                       return GetValue (row);
+               }
+       
+               public IndexEntry GetIndexEntry (int row)
+               {
+                       fs.Position = row * 4 + table_offset;
+                       int entry_offset = reader.ReadInt32 ();
+                       fs.Position = entry_offset;
+               
+                       return new IndexEntry (fs, reader, entry_offset);
+               }
+       }
+}
+
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/providers/EcmaDoc.cs b/mcs/tools/monkeydoc/MonkeyDoc/providers/EcmaDoc.cs
new file mode 100644 (file)
index 0000000..1d3c9fb
--- /dev/null
@@ -0,0 +1,236 @@
+using System;
+using System.Linq;
+using System.IO;
+using System.Text;
+using System.Xml;
+using System.Xml.Linq;
+using System.Collections.Generic;
+
+namespace MonkeyDoc.Providers
+{
+       // Common functionality between ecma-provider and ecmauncompiled-provider
+       internal class EcmaDoc
+       {
+               public static void PopulateTreeFromIndexFile (string indexFilePath,
+                                                             Tree tree,
+                                                             IDocStorage storage,
+                                                             Dictionary<string, XElement> nsSummaries,
+                                                             Func<XElement, string> indexGenerator = null)
+               {
+                       var root = tree.RootNode;
+                       int resID = 0;
+                       var asm = Path.GetDirectoryName (indexFilePath);
+
+                       storage = storage ?? new Storage.NullStorage ();
+                       // nsSummaries is allowed to be null if the user doesn't care about it
+                       nsSummaries = nsSummaries ?? new Dictionary<string, XElement> ();
+                       // default index generator uses a counter
+                       indexGenerator = indexGenerator ?? (_ => resID++.ToString ());
+
+                       using (var reader = XmlReader.Create (File.OpenRead (indexFilePath))) {
+                               reader.ReadToFollowing ("Types");
+                               var types = XElement.Load (reader.ReadSubtree ());
+
+                               foreach (var ns in types.Elements ("Namespace")) {
+                                       var nsName = (string)ns.Attribute ("Name");
+                                       nsName = !string.IsNullOrEmpty (nsName) ? nsName : "global";
+                                       var nsNode = root.GetOrCreateNode (nsName, "N:" + nsName);
+
+                                       XElement nsElements;
+                                       if (!nsSummaries.TryGetValue (nsName, out nsElements))
+                                               nsSummaries[nsName] = nsElements = new XElement ("elements",
+                                                                                                new XElement ("summary"),
+                                                                                                new XElement ("remarks"));
+
+                                       foreach (var type in ns.Elements ("Type")) {
+                                               // Add the XML file corresponding to the type to our storage
+                                               var id = indexGenerator (type);
+                                               string typeFilePath;
+                                               var typeDocument = EcmaDoc.LoadTypeDocument (asm, nsName, type.Attribute ("Name").Value, out typeFilePath);
+                                               if (typeDocument == null)
+                                                       continue;
+                                               using (var file = File.OpenRead (typeFilePath))
+                                                       storage.Store (id, file);
+                                               nsElements.Add (ExtractClassSummary (typeFilePath));
+
+                                               var typeCaption = EcmaDoc.GetTypeCaptionFromIndex (type);
+                                               var url = "ecma:" + id + '#' + typeCaption + '/';
+                                               typeCaption = EcmaDoc.GetTypeCaptionFromIndex (type, true);
+                                               var typeNode = nsNode.CreateNode (typeCaption, url);
+
+                                               // Add meta "Members" node
+                                               typeNode.CreateNode ("Members", "*");
+                                               var membersNode = typeDocument.Root.Element ("Members");
+                                               if (membersNode == null || !membersNode.Elements ().Any ())
+                                                       continue;
+                                               var members = membersNode
+                                                       .Elements ("Member")
+                                                       .ToLookup (EcmaDoc.GetMemberType);
+
+                                               foreach (var memberType in members) {
+                                                       // We pluralize the member type to get the caption and take the first letter as URL
+                                                       var node = typeNode.CreateNode (EcmaDoc.PluralizeMemberType (memberType.Key), memberType.Key[0].ToString ());
+                                                       var memberIndex = 0;
+
+                                                       var isCtors = memberType.Key[0] == 'C';
+
+                                                       // We do not escape much member name here
+                                                       foreach (var memberGroup in memberType.GroupBy (m => MakeMemberCaption (m, isCtors))) {
+                                                               if (memberGroup.Count () > 1) {
+                                                                       // Generate overload
+                                                                       var overloadCaption = MakeMemberCaption (memberGroup.First (), false);
+                                                                       var overloadNode = node.CreateNode (overloadCaption, overloadCaption);
+                                                                       foreach (var member in memberGroup)
+                                                                               overloadNode.CreateNode (MakeMemberCaption (member, true), (memberIndex++).ToString ());
+                                                                       overloadNode.Sort ();
+                                                               } else {
+                                                                       // We treat constructor differently by showing their argument list in all cases
+                                                                       node.CreateNode (MakeMemberCaption (memberGroup.First (), isCtors), (memberIndex++).ToString ());
+                                                               }
+                                                       }
+                                                       node.Sort ();
+                                               }
+                                       }
+
+                                       nsNode.Sort ();
+                               }
+                               root.Sort ();
+                       }
+               }
+
+               // Utility methods
+
+               public static XDocument LoadTypeDocument (string basePath, string nsName, string typeName)
+               {
+                       string dummy;
+                       return LoadTypeDocument (basePath, nsName, typeName, out dummy);
+               }
+
+               public static XDocument LoadTypeDocument (string basePath, string nsName, string typeName, out string finalPath)
+               {
+                       finalPath = Path.Combine (basePath, nsName, Path.ChangeExtension (typeName, ".xml"));
+                       if (!File.Exists (finalPath)) {
+                               Console.Error.WriteLine ("Warning: couldn't process type file `{0}' as it doesn't exist", finalPath);
+                               return null;
+                       }
+                       return XDocument.Load (finalPath);
+               }
+
+               public static string GetTypeCaptionFromIndex (XElement typeNodeFromIndex, bool full = false)
+               {
+                       var t = typeNodeFromIndex;
+                       var c = ((string)(t.Attribute ("DisplayName") ?? t.Attribute ("Name"))).Replace ('+', '.');
+                       if (full)
+                               c += " " + (string)t.Attribute ("Kind");
+                       return c;
+               }
+
+               public static string PluralizeMemberType (string memberType)
+               {
+                       switch (memberType) {
+                       case "Property":
+                               return "Properties";
+                       default:
+                               return memberType + "s";
+                       }
+               }
+
+               public static string GetMemberType (XElement m)
+               {
+                       return m.Attribute ("MemberName").Value.StartsWith ("op_") ? "Operator" : m.Element ("MemberType").Value;
+               }
+
+               public static string MakeMemberCaption (XElement member, bool withArguments)
+               {
+                       var caption = (string)member.Attribute ("MemberName");
+                       // Use type name instead of .ctor for cosmetic sake
+                       if (caption == ".ctor") {
+                               caption = (string)member.Ancestors ("Type").First ().Attribute ("Name");
+                               // If this is an inner type ctor, strip the parent type reference
+                               var plusIndex = caption.LastIndexOf ('+');
+                               if (plusIndex != -1)
+                                       caption = caption.Substring (plusIndex + 1);
+                       }
+                       if (caption.StartsWith ("op_")) {
+                               string sig;
+                               caption = MakeOperatorSignature (member, out sig);
+                               caption = withArguments ? sig : caption;
+                               return caption;
+                       }
+                       if (withArguments) {
+                               var args = member.Element ("Parameters");
+                               caption += '(';
+                               if (args != null && args.Elements ("Parameter").Any ()) {
+                                       caption += args.Elements ("Parameter")
+                                               .Select (p => (string)p.Attribute ("Type"))
+                                               .Aggregate ((p1, p2) => p1 + "," + p2);
+                               }
+                               caption += ')';
+                       }
+                       
+                       return caption;
+               }
+
+               internal static string MakeOperatorSignature (XElement member, out string memberSignature)
+               {
+                       string name = (string)member.Attribute ("MemberName");
+                       var nicename = name.Substring(3);
+                       memberSignature = null;
+
+                       switch (name) {
+                       // unary operators: no overloading possible     [ECMA-335 §10.3.1]
+                       case "op_UnaryPlus":                    // static     R operator+       (T)
+                       case "op_UnaryNegation":                // static     R operator-       (T)
+                       case "op_LogicalNot":                   // static     R operator!       (T)
+                       case "op_OnesComplement":               // static     R operator~       (T)
+                       case "op_Increment":                    // static     R operator++      (T)
+                       case "op_Decrement":                    // static     R operator--      (T)
+                       case "op_True":                         // static  bool operator true   (T)
+                       case "op_False":                        // static  bool operator false  (T)
+                       case "op_AddressOf":                    // static     R operator&       (T)
+                       case "op_PointerDereference":           // static     R operator*       (T)
+                               memberSignature = nicename;
+                               break;
+                       // conversion operators: overloading based on parameter and return type [ECMA-335 §10.3.3]
+                       case "op_Implicit":                    // static implicit operator R (T)
+                       case "op_Explicit":                    // static explicit operator R (T)
+                               nicename = name.EndsWith ("Implicit") ? "ImplicitConversion" : "ExplicitConversion";
+                               string arg = (string)member.Element ("Parameters").Element ("Parameter").Attribute ("Type");
+                               string ret = (string)member.Element ("ReturnValue").Element ("ReturnType");
+                               memberSignature = arg + " to " + ret;
+                               break;
+                       // binary operators: overloading is possible [ECMA-335 §10.3.2]
+                       default:
+                               memberSignature =
+                                       nicename + "("
+                                       + string.Join (",", member.Element ("Parameters").Elements ("Parameter").Select (p => (string)p.Attribute ("Type")))
+                                       + ")";
+                               break;
+                       }
+
+                       return nicename;
+               }
+
+               static XElement ExtractClassSummary (string typeFilePath)
+               {
+                       using (var reader = XmlReader.Create (typeFilePath)) {
+                               reader.ReadToFollowing ("Type");
+                               var name = reader.GetAttribute ("Name");
+                               var fullName = reader.GetAttribute ("FullName");
+                               reader.ReadToFollowing ("AssemblyName");
+                               var assemblyName = reader.ReadElementString ();
+                               reader.ReadToFollowing ("summary");
+                               var summary = reader.ReadInnerXml ();
+                               reader.ReadToFollowing ("remarks");
+                               var remarks = reader.ReadInnerXml ();
+
+                               return new XElement ("class",
+                                                    new XAttribute ("name", name ?? string.Empty),
+                                                    new XAttribute ("fullname", fullName ?? string.Empty),
+                                                    new XAttribute ("assembly", assemblyName ?? string.Empty),
+                                                    new XElement ("summary", new XCData (summary)),
+                                                    new XElement ("remarks", new XCData (remarks)));
+                       }
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/providers/addins-provider.cs b/mcs/tools/monkeydoc/MonkeyDoc/providers/addins-provider.cs
new file mode 100644 (file)
index 0000000..3768717
--- /dev/null
@@ -0,0 +1,136 @@
+// addins-provider.cs
+//
+// A provider to display Mono.Addins extension models
+//
+// Author:
+//   Lluis Sanchez Gual <lluis@novell.com>
+//
+// Copyright (c) 2007 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+//
+
+using System;
+using System.Linq;
+using System.Diagnostics;
+using System.Text;
+using System.IO;
+using System.Xml;
+using System.Collections.Generic;
+
+namespace MonkeyDoc.Providers
+{
+       public class AddinsProvider : Provider
+       {
+               string file;
+               
+               public AddinsProvider (string xmlModelFile)
+               {
+                       file = xmlModelFile;
+                       
+                       if (!File.Exists (file))
+                               throw new FileNotFoundException (String.Format ("The file `{0}' does not exist", file));
+               }
+
+               public override void PopulateTree (Tree tree)
+               {
+                       string fileId = Path.GetFileNameWithoutExtension (file);
+                       using (var f = File.OpenRead (file))
+                               tree.HelpSource.Storage.Store (fileId, f);
+
+                       XmlDocument doc = new XmlDocument ();
+                       doc.Load (file);
+                       
+                       foreach (XmlElement addin in doc.SelectNodes ("Addins/Addin")) {
+
+                               string addinId = addin.GetAttribute ("fullId");
+                               Node newNode = tree.RootNode.CreateNode (addin.GetAttribute ("name"), "addin:" + fileId + "#" + addinId);
+
+                               foreach (XmlElement node in addin.SelectNodes ("ExtensionPoint")) {
+                                       string target = "extension-point:" + fileId + "#" + addinId + "#" + node.GetAttribute ("path");
+                                       Node newExt = newNode.CreateNode (node.GetAttribute ("name"), target);
+                       
+                                       foreach (XmlElement en in node.SelectNodes ("ExtensionNode")) {
+                                               string nid = en.GetAttribute ("id");
+                                               string nname = en.GetAttribute ("name");
+                                               newExt.CreateNode (nname, "extension-node:" + fileId + "#" + addinId + "#" + nid);
+                                       }
+                               }
+                       }
+               }
+
+               public override void CloseTree (HelpSource hs, Tree tree)
+               {
+               }
+       }
+
+       public class AddinsHelpSource : HelpSource
+       {
+               public AddinsHelpSource (string base_file, bool create) : base (base_file, create) 
+               {
+               }
+               
+               internal protected const string AddinPrefix = "addin:";
+               internal protected const string ExtensionPrefix = "extension-point:";
+               internal protected const string ExtensionNodePrefix = "extension-node:";
+
+               public override bool CanHandleUrl (string url)
+               {
+                       return url.StartsWith (AddinPrefix, StringComparison.OrdinalIgnoreCase)
+                               || url.StartsWith (ExtensionPrefix, StringComparison.OrdinalIgnoreCase)
+                               || url.StartsWith (ExtensionNodePrefix, StringComparison.OrdinalIgnoreCase);
+               }
+
+               protected override string UriPrefix {
+                       get {
+                               return AddinPrefix;
+                       }
+               }
+               
+               public override DocumentType GetDocumentTypeForId (string id, out Dictionary<string, string> extraArgs)
+               {
+                       extraArgs = new Dictionary<string, string> ();
+                       var idParts = id.Split ('#');
+                       extraArgs["FileID"] = idParts[0];
+                       extraArgs["AddinID"] = idParts[1];
+                       extraArgs["NodeID"] = idParts[2];
+
+                       return DocumentType.AddinXml;
+               }
+
+               public override Node MatchNode (string url)
+               {
+                       var prefix = new[] { AddinPrefix, ExtensionPrefix, ExtensionNodePrefix }.First (p => url.StartsWith (p, StringComparison.OrdinalIgnoreCase));
+                       return base.MatchNode (prefix != null ? url.Substring (prefix.Length) : url);
+               }
+
+               public override Stream GetHelpStream (string id)
+               {
+                       var idParts = id.Split ('#');
+                       return base.GetHelpStream (idParts[0]);
+               }
+
+               public override Stream GetCachedHelpStream (string id)
+               {
+                       var idParts = id.Split ('#');
+                       return base.GetHelpStream (idParts[0]);
+               }
+       }
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/providers/ecma-provider.cs b/mcs/tools/monkeydoc/MonkeyDoc/providers/ecma-provider.cs
new file mode 100644 (file)
index 0000000..a30872b
--- /dev/null
@@ -0,0 +1,1070 @@
+//
+// The ecmaspec provider is for ECMA specifications
+//
+// Authors:
+//     John Luke (jluke@cfl.rr.com)
+//     Ben Maurer (bmaurer@users.sourceforge.net)
+//
+// Use like this:
+//   mono assembler.exe --ecmaspec DIRECTORY --out name
+//
+
+using System;
+using System.Linq;
+using System.IO;
+using System.Text;
+using System.Xml;
+using System.Xml.Linq;
+using System.Collections.Generic;
+
+using Lucene.Net.Index;
+using Lucene.Net.Documents;
+
+using MonkeyDoc.Ecma;
+using Mono.Utilities;
+
+namespace MonkeyDoc.Providers
+{
+       public enum EcmaNodeType {
+               Invalid,
+               Namespace,
+               Type,
+               Member,
+               Meta, // A node that's here to serve as a header for other node
+       }
+
+       public class EcmaProvider : Provider
+       {
+               HashSet<string> directories = new HashSet<string> ();
+
+               public EcmaProvider ()
+               {
+               }
+
+               public EcmaProvider (string baseDir)
+               {
+                       AddDirectory (baseDir);
+               }
+
+               public void AddDirectory (string directory)
+               {
+                       if (string.IsNullOrEmpty (directory))
+                               throw new ArgumentNullException ("directory");
+
+                       directories.Add (directory);
+               }
+
+               public override void PopulateTree (Tree tree)
+               {
+                       var storage = tree.HelpSource.Storage;
+                       var nsSummaries = new Dictionary<string, XElement> ();
+                       int resID = 0;
+
+                       foreach (var asm in directories) {
+                               var indexFilePath = Path.Combine (asm, "index.xml");
+                               if (!File.Exists (indexFilePath)) {
+                                       Console.Error.WriteLine ("Warning: couldn't process directory `{0}' as it has no index.xml file", asm);
+                                       continue;
+                               }
+
+                               EcmaDoc.PopulateTreeFromIndexFile (indexFilePath, tree, storage, nsSummaries, _ => resID++.ToString ());
+                       }
+
+                       foreach (var summary in nsSummaries)
+                               storage.Store ("xml.summary." + summary.Key, summary.Value.ToString ());
+
+                       var masterSummary = new XElement ("elements",
+                                                         directories
+                                                         .SelectMany (d => Directory.EnumerateFiles (d, "ns-*.xml"))
+                                                         .Select (ExtractNamespaceSummary));
+                       storage.Store ("mastersummary.xml", masterSummary.ToString ());
+               }
+
+               XElement ExtractNamespaceSummary (string nsFile)
+               {
+                       using (var reader = XmlReader.Create (nsFile)) {
+                               reader.ReadToFollowing ("Namespace");
+                               var name = reader.GetAttribute ("Name");
+                               reader.ReadToFollowing ("summary");
+                               var summary = reader.ReadInnerXml ();
+                               reader.ReadToFollowing ("remarks");
+                               var remarks = reader.ReadInnerXml ();
+
+                               return new XElement ("namespace",
+                                                    new XAttribute ("ns", name ?? string.Empty),
+                                                    new XElement ("summary", new XCData (summary)),
+                                                    new XElement ("remarks", new XCData (remarks)));
+                       }
+               }
+
+               public override void CloseTree (HelpSource hs, Tree tree)
+               {
+                       AddImages (hs);
+                       AddExtensionMethods (hs);
+               }
+
+               void AddEcmaXml (HelpSource hs)
+               {
+                       var xmls = directories
+                               .SelectMany (Directory.EnumerateDirectories) // Assemblies
+                               .SelectMany (Directory.EnumerateDirectories) // Namespaces
+                               .SelectMany (Directory.EnumerateFiles)
+                               .Where (f => f.EndsWith (".xml")); // Type XML files
+
+                       int resID = 0;
+                       foreach (var xml in xmls)
+                               using (var file = File.OpenRead (xml))
+                                       hs.Storage.Store ((resID++).ToString (), file);
+               }
+
+               void AddImages (HelpSource hs)
+               {
+                       var imgs = directories
+                               .SelectMany (Directory.EnumerateDirectories)
+                               .Select (d => Path.Combine (d, "_images"))
+                               .Where (Directory.Exists)
+                               .SelectMany (Directory.EnumerateFiles);
+
+                       foreach (var img in imgs)
+                               using (var file = File.OpenRead (img))
+                                       hs.Storage.Store (Path.GetFileName (img), file);
+               }
+
+               void AddExtensionMethods (HelpSource hs)
+               {
+                       var extensionMethods = directories
+                               .SelectMany (Directory.EnumerateDirectories)
+                               .Select (d => Path.Combine (d, "index.xml"))
+                               .Where (File.Exists)
+                               .Select (f => {
+                                       using (var file = File.OpenRead (f)) {
+                                               var reader = XmlReader.Create (file);
+                                               reader.ReadToFollowing ("ExtensionMethods");
+                                               return reader.ReadInnerXml ();
+                                       }
+                           })
+                           .DefaultIfEmpty (string.Empty);
+
+                       hs.Storage.Store ("ExtensionMethods.xml",
+                                         "<ExtensionMethods>" + extensionMethods.Aggregate (string.Concat) + "</ExtensionMethods>");
+               }
+
+               IEnumerable<string> GetEcmaXmls ()
+               {
+                       return directories
+                               .SelectMany (Directory.EnumerateDirectories) // Assemblies
+                               .SelectMany (Directory.EnumerateDirectories) // Namespaces
+                               .SelectMany (Directory.EnumerateFiles)
+                               .Where (f => f.EndsWith (".xml")); // Type XML files
+               }
+       }
+
+       public class EcmaHelpSource : HelpSource
+       {
+               const string EcmaPrefix = "ecma:";
+               EcmaUrlParser parser = new EcmaUrlParser ();
+               LRUCache<string, Node> cache = new LRUCache<string, Node> (4);
+
+               public EcmaHelpSource (string base_file, bool create) : base (base_file, create)
+               {
+               }
+
+               protected EcmaHelpSource () : base ()
+               {
+               }
+
+               protected override string UriPrefix {
+                       get {
+                               return EcmaPrefix;
+                       }
+               }
+
+               public override bool CanHandleUrl (string url)
+               {
+                       if (url.Length > 2 && url[1] == ':') {
+                               switch (url[0]) {
+                               case 'T':
+                               case 'M':
+                               case 'C':
+                               case 'P':
+                               case 'E':
+                               case 'F':
+                               case 'N':
+                               case 'O':
+                                       return true;
+                               }
+                       }
+                       return base.CanHandleUrl (url);
+               }
+
+               // Clean the extra paramers in the id
+               public override Stream GetHelpStream (string id)
+               {
+                       var idParts = id.Split ('?');
+                       return base.GetHelpStream (idParts[0]);
+               }
+
+               public override Stream GetCachedHelpStream (string id)
+               {
+                       var idParts = id.Split ('?');
+                       return base.GetCachedHelpStream (idParts[0]);
+               }
+
+               public override DocumentType GetDocumentTypeForId (string id, out Dictionary<string, string> extraParams)
+               {
+                       extraParams = null;
+                       int interMark = id.LastIndexOf ('?');
+                       if (interMark != -1)
+                               extraParams = id.Substring (interMark)
+                                       .Split ('&')
+                                       .Select (nvp => {
+                                               var eqIdx = nvp.IndexOf ('=');
+                                               return new { Key = nvp.Substring (0, eqIdx < 0 ? nvp.Length : eqIdx), Value = nvp.Substring (eqIdx + 1) };
+                                       })
+                                       .ToDictionary (kvp => kvp.Key, kvp => kvp.Value );
+                       return DocumentType.EcmaXml;
+               }
+
+               public override string GetPublicUrl (Node node)
+               {
+                       string url = string.Empty;
+                       var type = GetNodeType (node);
+                       //Console.WriteLine ("GetPublicUrl {0} : {1} [{2}]", node.Element, node.Caption, type.ToString ());
+                       switch (type) {
+                       case EcmaNodeType.Namespace:
+                               return node.Element; // A namespace node has already a well formated internal url
+                       case EcmaNodeType.Type:
+                               return MakeTypeNodeUrl (node);
+                       case EcmaNodeType.Meta:
+                               return MakeTypeNodeUrl (GetNodeTypeParent (node)) + GenerateMetaSuffix (node);
+                       case EcmaNodeType.Member:
+                               var typeChar = GetNodeMemberTypeChar (node);
+                               var parentNode = GetNodeTypeParent (node);
+                               var typeNode = MakeTypeNodeUrl (parentNode).Substring (2);
+                               return typeChar + ":" + typeNode + MakeMemberNodeUrl (typeChar, node);
+                       default:
+                               return null;
+                       }
+               }
+
+               string MakeTypeNodeUrl (Node node)
+               {
+                       // A Type node has a Element property of the form: 'ecma:{number}#{typename}/'
+                       var hashIndex = node.Element.IndexOf ('#');
+                       var typeName = node.Element.Substring (hashIndex + 1, node.Element.Length - hashIndex - 2);
+                       return "T:" + node.Parent.Caption + '.' + typeName.Replace ('.', '+');
+               }
+
+               string MakeMemberNodeUrl (char typeChar, Node node)
+               {
+                       // We clean inner type ctor name which may contain the outer type name
+                       var caption = node.Caption;
+
+                       // Sanitize constructor caption of inner types
+                       if (typeChar == 'C') {
+                               int lastDot = -1;
+                               for (int i = 0; i < caption.Length && caption[i] != '('; i++)
+                                       lastDot = caption[i] == '.' ? i : lastDot;
+                               return lastDot == -1 ? '.' + caption : caption.Substring (lastDot);
+                       }
+
+                       /* We handle type conversion operator by checking if the name contains " to "
+                        * (as in 'foo to bar') and we generate a corresponding conversion signature
+                        */
+                       if (typeChar == 'O' && caption.IndexOf (" to ") != -1) {
+                               var parts = caption.Split (' ');
+                               return "." + node.Parent.Caption + "(" + parts[0] + ", " + parts[2] + ")";
+                       }
+
+                       /* The goal here is to treat method which are explicit interface definition
+                        * such as 'void IDisposable.Dispose ()' for which the caption is a dot
+                        * expression thus colliding with the ecma parser.
+                        * If the first non-alpha character in the caption is a dot then we have an
+                        * explicit member implementation (we assume the interface has namespace)
+                        */
+                       var firstNonAlpha = caption.FirstOrDefault (c => !char.IsLetterOrDigit (c));
+                       if (firstNonAlpha == '.')
+                               return "$" + caption;
+
+                       return "." + caption;
+               }
+
+               EcmaNodeType GetNodeType (Node node)
+               {
+                       // We guess the node type by checking the depth level it's at in the tree
+                       int level = GetNodeLevel (node);
+                       switch (level) {
+                       case 0:
+                               return EcmaNodeType.Namespace;
+                       case 1:
+                               return EcmaNodeType.Type;
+                       case 2:
+                               return EcmaNodeType.Meta;
+                       case 3: // Here it's either a member or, in case of overload, a meta
+                               return node.IsLeaf ? EcmaNodeType.Member : EcmaNodeType.Meta;
+                       case 4: // At this level, everything is necessarily a member
+                               return EcmaNodeType.Member;
+                       default:
+                               return EcmaNodeType.Invalid;
+                       }
+               }
+
+               int GetNodeLevel (Node node)
+               {
+                       int i = 0;
+                       for (; !node.Element.StartsWith ("root:/", StringComparison.OrdinalIgnoreCase); i++) {
+                               //Console.WriteLine ("\tLevel {0} : {1} {2}", i, node.Element, node.Caption);
+                               node = node.Parent;
+                       }
+                       return i - 1;
+               }
+
+               char GetNodeMemberTypeChar (Node node)
+               {
+                       int level = GetNodeLevel (node);
+                       // We try to reach the member group node depending on node nested level
+                       switch (level) {
+                       case 2:
+                               return node.Element[0];
+                       case 3:
+                               return node.Parent.Element[0];
+                       case 4:
+                               return node.Parent.Parent.Element[0];
+                       default:
+                               throw new ArgumentException ("node", "Couldn't determine member type of node `" + node.Caption + "'");
+                       }
+               }
+
+               Node GetNodeTypeParent (Node node)
+               {
+                       // Type nodes are always at level 2 so we just need to get there
+                       while (node != null && node.Parent != null && !node.Parent.Parent.Element.StartsWith ("root:/", StringComparison.OrdinalIgnoreCase))
+                               node = node.Parent;
+                       return node;
+               }
+
+               string GenerateMetaSuffix (Node node)
+               {
+                       string suffix = string.Empty;
+                       // A meta node has always a type element to begin with
+                       while (GetNodeType (node) != EcmaNodeType.Type) {
+                               suffix = '/' + node.Element + suffix;
+                               node = node.Parent;
+                       }
+                       return suffix;
+               }
+
+               public override string GetInternalIdForUrl (string url, out Node node)
+               {
+                       var id = string.Empty;
+                       node = null;
+
+                       if (!url.StartsWith (UriPrefix, StringComparison.OrdinalIgnoreCase)) {
+                               node = MatchNode (url);
+                               if (node == null)
+                                       return null;
+                               id = node.GetInternalUrl ();
+                       }
+
+                       string hash;
+                       id = GetInternalIdForInternalUrl (id, out hash);
+
+                       return id + GetArgs (hash, node);
+               }
+
+               public string GetInternalIdForInternalUrl (string internalUrl, out string hash)
+               {
+                       var id = internalUrl;
+                       if (id.StartsWith (UriPrefix, StringComparison.OrdinalIgnoreCase))
+                               id = id.Substring (UriPrefix.Length);
+                       else if (id.StartsWith ("N:", StringComparison.OrdinalIgnoreCase))
+                               id = "xml.summary." + id.Substring ("N:".Length);
+
+                       var hashIndex = id.IndexOf ('#');
+                       hash = string.Empty;
+                       if (hashIndex != -1) {
+                               hash = id.Substring (hashIndex + 1);
+                               id = id.Substring (0, hashIndex);
+                       }
+
+                       return id;
+               }
+
+               public override Node MatchNode (string url)
+               {
+                       Node node = null;
+                       if ((node = cache.Get (url)) == null) {
+                               node = InternalMatchNode (url);
+                               if (node != null)
+                                       cache.Put (url, node);
+                       }
+                       return node;
+               }
+
+               public Node InternalMatchNode (string url)
+               {
+                       Node result = null;
+                       EcmaDesc desc;
+                       if (!parser.TryParse (url, out desc))
+                               return null;
+
+                       // Namespace search
+                       Node currentNode = Tree.RootNode;
+                       Node searchNode = new Node () { Caption = desc.Namespace };
+                       int index = currentNode.Nodes.BinarySearch (searchNode, EcmaGenericNodeComparer.Instance);
+                       if (index >= 0)
+                               result = currentNode.Nodes[index];
+                       if (desc.DescKind == EcmaDesc.Kind.Namespace || index < 0)
+                               return result;
+
+                       // Type search
+                       currentNode = result;
+                       result = null;
+                       searchNode.Caption = desc.ToCompleteTypeName ();
+                       index = currentNode.Nodes.BinarySearch (searchNode, EcmaTypeNodeComparer.Instance);
+                       if (index >= 0)
+                               result = currentNode.Nodes[index];
+                       if ((desc.DescKind == EcmaDesc.Kind.Type && !desc.IsEtc) || index < 0)
+                               return result;
+
+                       // Member selection
+                       currentNode = result;
+                       result = null;
+                       var caption = desc.IsEtc ? EtcKindToCaption (desc.Etc) : MemberKindToCaption (desc.DescKind);
+                       currentNode = FindNodeForCaption (currentNode.Nodes, caption);
+                       if (currentNode == null 
+                           || (desc.IsEtc && desc.DescKind == EcmaDesc.Kind.Type && string.IsNullOrEmpty (desc.EtcFilter)))
+                               return currentNode;
+
+                       // Member search
+                       result = null;
+                       var format = desc.DescKind == EcmaDesc.Kind.Constructor ? EcmaDesc.Format.WithArgs : EcmaDesc.Format.WithoutArgs;
+                       searchNode.Caption = desc.ToCompleteMemberName (format);
+                       index = currentNode.Nodes.BinarySearch (searchNode, EcmaGenericNodeComparer.Instance);
+                       if (index < 0)
+                               return null;
+                       result = currentNode.Nodes[index];
+                       if (result.Nodes.Count == 0 || desc.IsEtc)
+                               return result;
+
+                       // Overloads search
+                       currentNode = result;
+                       searchNode.Caption = desc.ToCompleteMemberName (EcmaDesc.Format.WithArgs);
+                       index = currentNode.Nodes.BinarySearch (searchNode, EcmaGenericNodeComparer.Instance);
+                       if (index < 0)
+                               return result;
+                       result = result.Nodes[index];
+                       
+                       return result;
+               }
+
+               // This comparer returns the answer straight from caption comparison
+               class EcmaGenericNodeComparer : IComparer<Node>
+               {
+                       public static readonly EcmaGenericNodeComparer Instance = new EcmaGenericNodeComparer ();
+
+                       public int Compare (Node n1, Node n2)
+                       {
+                               return string.Compare (n1.Caption, n2.Caption, StringComparison.Ordinal);
+                       }
+               }
+
+               // This comparer take into account the space in the caption
+               class EcmaTypeNodeComparer : IComparer<Node>
+               {
+                       public static readonly EcmaTypeNodeComparer Instance = new EcmaTypeNodeComparer ();
+
+                       public int Compare (Node n1, Node n2)
+                       {
+                               int length1 = CaptionLength (n1.Caption);
+                               int length2 = CaptionLength (n2.Caption);
+
+                               return string.Compare (n1.Caption, 0, n2.Caption, 0, Math.Max (length1, length2), StringComparison.Ordinal);
+                       }
+
+                       int CaptionLength (string caption)
+                       {
+                               var length = caption.LastIndexOf (' ');
+                               return length == -1 ? caption.Length : length;
+                       }
+               }
+
+               string EtcKindToCaption (char etc)
+               {
+                       switch (etc) {
+                       case 'M':
+                               return "Methods";
+                       case 'P':
+                               return "Properties";
+                       case 'C':
+                               return "Constructors";
+                       case 'F':
+                               return "Fields";
+                       case 'E':
+                               return "Events";
+                       case 'O':
+                               return "Operators";
+                       case '*':
+                               return "Members";
+                       default:
+                               return null;
+                       }
+               }
+
+               string MemberKindToCaption (EcmaDesc.Kind kind)
+               {
+                       switch (kind) {
+                       case EcmaDesc.Kind.Method:
+                               return "Methods";
+                       case EcmaDesc.Kind.Property:
+                               return "Properties";
+                       case EcmaDesc.Kind.Constructor:
+                               return "Constructors";
+                       case EcmaDesc.Kind.Field:
+                               return "Fields";
+                       case EcmaDesc.Kind.Event:
+                               return "Events";
+                       case EcmaDesc.Kind.Operator:
+                               return "Operators";
+                       default:
+                               return null;
+                       }
+               }
+
+               Node FindNodeForCaption (List<Node> nodes, string caption)
+               {
+                       foreach (var node in nodes)
+                               if (node.Caption.Equals (caption, StringComparison.OrdinalIgnoreCase))
+                                       return node;
+                       return null;
+               }
+
+               string GetArgs (string hash, Node node)
+               {
+                       var args = new Dictionary<string, string> ();
+                       
+                       args["source-id"] = SourceID.ToString ();
+                       
+                       if (node != null) {
+                               var nodeType = GetNodeType (node);
+                               switch (nodeType) {
+                               case EcmaNodeType.Namespace:
+                                       args["show"] = "namespace";
+                                       args["namespace"] = node.Element.Substring ("N:".Length);
+                                       break;
+                               case EcmaNodeType.Type:
+                                       args["show"] = "typeoverview";
+                                       break;
+                               case EcmaNodeType.Member:
+                               case EcmaNodeType.Meta:
+                                       switch (GetNodeMemberTypeChar (node)){
+                                       case 'C':
+                                               args["membertype"] = "Constructor";
+                                               break;
+                                       case 'M':
+                                               args["membertype"] = "Method";
+                                               break;
+                                       case 'P':
+                                               args["membertype"] = "Property";
+                                               break;
+                                       case 'F':
+                                               args["membertype"] = "Field";
+                                               break;
+                                       case 'E':
+                                               args["membertype"] = "Event";
+                                               break;
+                                       case 'O':
+                                               args["membertype"] = "Operator";
+                                               break;
+                                       case 'X':
+                                               args["membertype"] = "ExtensionMethod";
+                                               break;
+                                       case '*':
+                                               args["membertype"] = "All";
+                                               break;
+                                       }
+
+                                       if (nodeType == EcmaNodeType.Meta) {
+                                               args["show"] = "members";
+                                               args["index"] = "all";
+                                       } else {
+                                               args["show"] = "member";
+                                               args["index"] = node.Element;
+                                       }
+                                       break;
+                               }
+                       }
+
+                       if (!string.IsNullOrEmpty (hash))
+                               args["hash"] = hash;
+
+                       return "?" + string.Join ("&", args.Select (kvp => kvp.Key == kvp.Value ? kvp.Key : kvp.Key + '=' + kvp.Value));
+               }
+
+               public override void PopulateIndex (IndexMaker index_maker)
+               {
+                       foreach (Node ns_node in Tree.RootNode.Nodes){
+                               foreach (Node type_node in ns_node.Nodes){
+                                       string typename = type_node.Caption.Substring (0, type_node.Caption.IndexOf (' '));
+                                       string full = ns_node.Caption + "." + typename;
+
+                                       string doc_tag = GetKindFromCaption (type_node.Caption);
+                                       string url = type_node.PublicUrl;
+
+                                       //
+                                       // Add MonoMac/MonoTouch [Export] attributes, those live only in classes
+                                       //
+                                       XDocument type_doc = null;
+                                       ILookup<string, XElement> prematchedMembers = null;
+                                       bool hasExports = doc_tag == "Class" && (ns_node.Caption.StartsWith ("MonoTouch") || ns_node.Caption.StartsWith ("MonoMac"));
+                                       if (hasExports) {
+                                               try {
+                                                       string rest, hash;
+                                                       var id = GetInternalIdForInternalUrl (type_node.GetInternalUrl (), out hash);
+                                                       type_doc = XDocument.Load (GetHelpStream (id));
+                                                       prematchedMembers = type_doc.Root.Element ("Members").Elements ("Member").ToLookup (n => (string)n.Attribute ("MemberName"), n => n);
+                                               } catch (Exception e) {
+                                                       Console.WriteLine ("Problem processing {0} for MonoTouch/MonoMac exports\n\n{0}", e);
+                                                       hasExports = false;
+                                               }
+                                       }
+
+                                       if (doc_tag == "Class" || doc_tag == "Structure" || doc_tag == "Interface"){
+                                               index_maker.Add (type_node.Caption, typename, url);
+                                               index_maker.Add (full + " " + doc_tag, full, url);
+
+                                               foreach (Node c in type_node.Nodes){
+                                                       switch (c.Caption){
+                                                       case "Constructors":
+                                                               index_maker.Add ("  constructors", typename+"0", url + "/C");
+                                                               break;
+                                                       case "Fields":
+                                                               index_maker.Add ("  fields", typename+"1", url + "/F");
+                                                               break;
+                                                       case "Events":
+                                                               index_maker.Add ("  events", typename+"2", url + "/E");
+                                                               break;
+                                                       case "Properties":
+                                                               index_maker.Add ("  properties", typename+"3", url + "/P");
+                                                               break;
+                                                       case "Methods":
+                                                               index_maker.Add ("  methods", typename+"4", url + "/M");
+                                                               break;
+                                                       case "Operators":
+                                                               index_maker.Add ("  operators", typename+"5", url + "/O");
+                                                               break;
+                                                       }
+                                               }
+
+                                               //
+                                               // Now repeat, but use a different sort key, to make sure we come after
+                                               // the summary data above, start the counter at 6
+                                               //
+                                               string keybase = typename + "6.";
+
+                                               foreach (Node c in type_node.Nodes){
+                                                       var type = c.Caption[0];
+
+                                                       foreach (Node nc in c.Nodes) {
+                                                               string res = nc.Caption;
+                                                               string nurl = nc.PublicUrl;
+
+                                                               // Process exports
+                                                               if (hasExports && (type == 'C' || type == 'M' || type == 'P')) {
+                                                                       try {
+                                                                               var member = GetMemberFromCaption (type_doc, type == 'C' ? ".ctor" : res, false, prematchedMembers);
+                                                                               var exports = member.Descendants ("AttributeName").Where (a => a.Value.Contains ("Foundation.Export"));
+                                                                               foreach (var exportNode in exports) {
+                                                                                       var parts = exportNode.Value.Split ('"');
+                                                                                       if (parts.Length != 3) {
+                                                                                               Console.WriteLine ("Export attribute not found or not usable in {0}", exportNode);
+                                                                                       } else {
+                                                                                               var export = parts[1];
+                                                                                               index_maker.Add (export + " selector", export, nurl);
+                                                                                       }
+                                                                               }
+                                                                       } catch (Exception e) {
+                                                                               Console.WriteLine ("Problem processing {0}/{1} for MonoTouch/MonoMac exports\n\n{2}", nurl, res, e);
+                                                                       }
+                                                               }
+
+                                                               switch (type){
+                                                               case 'C':
+                                                                       break;
+                                                               case 'F':
+                                                                       index_maker.Add (String.Format ("{0}.{1} field", typename, res),
+                                                                                        keybase + res, nurl);
+                                                                       index_maker.Add (String.Format ("{0} field", res), res, nurl);
+                                                                       break;
+                                                               case 'E':
+                                                                       index_maker.Add (String.Format ("{0}.{1} event", typename, res),
+                                                                                        keybase + res, nurl);
+                                                                       index_maker.Add (String.Format ("{0} event", res), res, nurl);
+                                                                       break;
+                                                               case 'P':
+                                                                       index_maker.Add (String.Format ("{0}.{1} property", typename, res),
+                                                                                        keybase + res, nurl);
+                                                                       index_maker.Add (String.Format ("{0} property", res), res, nurl);
+                                                                       break;
+                                                               case 'M':
+                                                                       index_maker.Add (String.Format ("{0}.{1} method", typename, res),
+                                                                                        keybase + res, nurl);
+                                                                       index_maker.Add (String.Format ("{0} method", res), res, nurl);
+                                                                       break;
+                                                               case 'O':
+                                                                       index_maker.Add (String.Format ("{0}.{1} operator", typename, res),
+                                                                                        keybase + res, nurl);
+                                                                       break;
+                                                               }
+                                                       }
+                                               }
+                                       } else if (doc_tag == "Enumeration"){
+                                               //
+                                               // Enumerations: add the enumeration values
+                                               //
+                                               index_maker.Add (type_node.Caption, typename, url);
+                                               index_maker.Add (full + " " + doc_tag, full, url);
+
+                                               // Now, pull the values.
+                                               string rest, hash;
+                                               var id = GetInternalIdForInternalUrl (type_node.GetInternalUrl (), out hash);
+                                               var xdoc = XDocument.Load (GetHelpStream (id));
+                                               if (xdoc == null)
+                                                       continue;
+
+                                               var members = xdoc.Root.Element ("Members").Elements ("Members");
+                                               if (members == null)
+                                                       continue;
+
+                                               foreach (var member_node in members){
+                                                       string enum_value = member_node.Attribute ("MemberName").Value;
+                                                       string caption = enum_value + " value";
+                                                       index_maker.Add (caption, caption, url);
+                                               }
+                                       } else if (doc_tag == "Delegate"){
+                                               index_maker.Add (type_node.Caption, typename, url);
+                                               index_maker.Add (full + " " + doc_tag, full, url);
+                                       }
+                               }
+                       }
+               }
+
+
+               public override void PopulateSearchableIndex (IndexWriter writer)
+               {
+                       StringBuilder text = new StringBuilder ();
+                       SearchableDocument searchDoc = new SearchableDocument ();
+
+                       foreach (Node ns_node in Tree.RootNode.Nodes) {
+                               foreach (Node type_node in ns_node.Nodes) {
+                                       string typename = type_node.Caption.Substring (0, type_node.Caption.IndexOf (' '));
+                                       string full = ns_node.Caption + "." + typename;
+                                       string url = type_node.PublicUrl;
+                                       string doc_tag = GetKindFromCaption (type_node.Caption);
+                                       string rest, hash;
+                                       var id = GetInternalIdForInternalUrl (type_node.GetInternalUrl (), out hash);
+                                       var xdoc = XDocument.Load (GetHelpStream (id));
+                                       if (xdoc == null)
+                                               continue;
+                                       if (string.IsNullOrEmpty (doc_tag)) {
+                                               Console.WriteLine (type_node.Caption);
+                                               continue;
+                                       }       
+
+                                       // For classes, structures or interfaces add a doc for the overview and
+                                       // add a doc for every constructor, method, event, ...
+                                       // doc_tag == "Class" || doc_tag == "Structure" || doc_tag == "Interface"
+                                       if (doc_tag[0] == 'C' || doc_tag[0] == 'S' || doc_tag[0] == 'I') {
+                                               // Adds a doc for every overview of every type
+                                               SearchableDocument doc = searchDoc.Reset ();
+                                               doc.Title = type_node.Caption;
+                                               doc.HotText = typename;
+                                               doc.Url = url;
+                                               doc.FullTitle = full;
+
+                                               var node_sel = xdoc.Root.Element ("Docs");
+                                               text.Clear ();
+                                               GetTextFromNode (node_sel, text);
+                                               doc.Text = text.ToString ();
+
+                                               text.Clear ();
+                                               GetExamples (node_sel, text);
+                                               doc.Examples = text.ToString ();
+
+                                               writer.AddDocument (doc.LuceneDoc);
+                                               var exportParsable = doc_tag[0] == 'C' && (ns_node.Caption.StartsWith ("MonoTouch") || ns_node.Caption.StartsWith ("MonoMac"));
+
+                                               //Add docs for contructors, methods, etc.
+                                               foreach (Node c in type_node.Nodes) { // c = Constructors || Fields || Events || Properties || Methods || Operators
+                                                       if (c.Element == "*")
+                                                               continue;
+                                                       const float innerTypeBoost = 0.2f;
+
+                                                       IEnumerable<Node> ncnodes = c.Nodes;
+                                                       // The rationale is that we need to properly handle method overloads
+                                                       // so for those method node which have children, flatten them
+                                                       if (c.Caption == "Methods") {
+                                                               ncnodes = ncnodes
+                                                                       .Where (n => n.Nodes == null || n.Nodes.Count == 0)
+                                                                       .Concat (ncnodes.Where (n => n.Nodes.Count > 0).SelectMany (n => n.Nodes));
+                                                       } else if (c.Caption == "Operators") {
+                                                               ncnodes = ncnodes
+                                                                       .Where (n => !n.Caption.EndsWith ("Conversion"))
+                                                                       .Concat (ncnodes.Where (n => n.Caption.EndsWith ("Conversion")).SelectMany (n => n.Nodes));
+                                                       }
+
+                                                       var prematchedMembers = xdoc.Root.Element ("Members").Elements ("Member").ToLookup (n => (string)n.Attribute ("MemberName"), n => n);
+
+                                                       foreach (Node nc in ncnodes) {
+                                                               var docsNode = GetDocsFromCaption (xdoc, c.Caption[0] == 'C' ? ".ctor" : nc.Caption, c.Caption[0] == 'O', prematchedMembers);
+                                                               if (docsNode == null) {
+                                                                       Console.Error.WriteLine ("Problem: {0}", nc.PublicUrl);
+                                                                       continue;
+                                                               }
+
+                                                               SearchableDocument doc_nod = searchDoc.Reset ();
+                                                               doc_nod.Title = LargeName (nc) + " " + EtcKindToCaption (c.Caption[0]);
+                                                               doc_nod.FullTitle = ns_node.Caption + '.' + typename + "::" + nc.Caption;
+                                                               doc_nod.HotText = string.Empty;
+
+                                                               /* Disable constructors hottext indexing as it's often "polluting" search queries
+                                                                  because it has the same hottext than standard types */
+                                                               if (c.Caption != "Constructors") {
+                                                                       //dont add the parameters to the hottext
+                                                                       int ppos = nc.Caption.IndexOf ('(');
+                                                                       doc_nod.HotText = ppos != -1 ? nc.Caption.Substring (0, ppos) : nc.Caption;
+                                                               }
+
+                                                               var urlnc = nc.PublicUrl;
+                                                               doc_nod.Url = urlnc;
+
+                                                               text.Clear ();
+                                                               GetTextFromNode (docsNode, text);
+                                                               doc_nod.Text = text.ToString ();
+
+                                                               text.Clear ();
+                                                               GetExamples (docsNode, text);
+                                                               doc_nod.Examples = text.ToString ();
+
+                                                               Document lucene_doc = doc_nod.LuceneDoc;
+                                                               lucene_doc.Boost = innerTypeBoost;
+                                                               writer.AddDocument (lucene_doc);
+
+                                                               // Objective-C binding specific parsing of [Export] attributes
+                                                               if (exportParsable) {
+                                                                       try {
+                                                                               var exports = docsNode.Parent.Elements ("Attributes").Elements ("Attribute").Elements ("AttributeName")
+                                                                                       .Select (a => (string)a).Where (txt => txt.Contains ("Foundation.Export"));
+
+                                                                               foreach (var exportNode in exports) {
+                                                                                       var parts = exportNode.Split ('"');
+                                                                                       if (parts.Length != 3) {
+                                                                                               Console.WriteLine ("Export attribute not found or not usable in {0}", exportNode);
+                                                                                               continue;
+                                                                                       }
+
+                                                                                       var export = parts[1];
+                                                                                       var export_node = searchDoc.Reset ();
+                                                                                       export_node.Title = export + " Export";
+                                                                                       export_node.FullTitle = ns_node.Caption + '.' + typename + "::" + export;
+                                                                                       export_node.Url = urlnc;
+                                                                                       export_node.HotText = export;
+                                                                                       export_node.Text = string.Empty;
+                                                                                       export_node.Examples = string.Empty;
+                                                                                       lucene_doc = export_node.LuceneDoc;
+                                                                                       lucene_doc.Boost = innerTypeBoost;
+                                                                                       writer.AddDocument (lucene_doc);
+                                                                               }
+                                                                       } catch (Exception e){
+                                                                               Console.WriteLine ("Problem processing {0} for MonoTouch/MonoMac exports\n\n{0}", e);
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       // doc_tag == "Enumeration"
+                                       } else if (doc_tag[0] == 'E'){
+                                               var members = xdoc.Root.Element ("Members").Elements ("Member");
+                                               if (members == null)
+                                                       continue;
+
+                                               text.Clear ();
+                                               foreach (var member_node in members) {
+                                                       string enum_value = (string)member_node.Attribute ("MemberName");
+                                                       text.Append (enum_value);
+                                                       text.Append (" ");
+                                                       GetTextFromNode (member_node.Element ("Docs"), text);
+                                                       text.AppendLine ();
+                                               }
+
+                                               SearchableDocument doc = searchDoc.Reset ();
+
+                                               text.Clear ();
+                                               GetExamples (xdoc.Root.Element ("Docs"), text);
+                                               doc.Examples = text.ToString ();
+
+                                               doc.Title = type_node.Caption;
+                                               doc.HotText = (string)xdoc.Root.Attribute ("Name");
+                                               doc.FullTitle = full;
+                                               doc.Url = url;
+                                               doc.Text = text.ToString();
+                                               writer.AddDocument (doc.LuceneDoc);
+                                       // doc_tag == "Delegate"
+                                       } else if (doc_tag[0] == 'D'){
+                                               SearchableDocument doc = searchDoc.Reset ();
+                                               doc.Title = type_node.Caption;
+                                               doc.HotText = (string)xdoc.Root.Attribute ("Name");
+                                               doc.FullTitle = full;
+                                               doc.Url = url;
+
+                                               var node_sel = xdoc.Root.Element ("Docs");
+
+                                               text.Clear ();
+                                               GetTextFromNode (node_sel, text);
+                                               doc.Text = text.ToString();
+
+                                               text.Clear ();
+                                               GetExamples (node_sel, text);
+                                               doc.Examples = text.ToString();
+
+                                               writer.AddDocument (doc.LuceneDoc);
+                                       }
+                               }
+                       }
+               }
+
+               string GetKindFromCaption (string s)
+               {
+                       int p = s.LastIndexOf (' ');
+                       if (p > 0)
+                               return s.Substring (p + 1);
+                       return null;
+               }
+
+               // Extract the interesting text from the docs node
+               void GetTextFromNode (XElement n, StringBuilder sb)
+               {
+                       // Include the text content of the docs
+                       sb.AppendLine (n.Value);
+                       foreach (var tag in n.Descendants ())
+                               //include the url to which points the see tag and the name of the parameter
+                               if ((tag.Name.LocalName.Equals ("see", StringComparison.Ordinal) || tag.Name.LocalName.Equals ("paramref", StringComparison.Ordinal))
+                                   && tag.HasAttributes)
+                                       sb.AppendLine ((string)tag.Attributes ().First ());
+               }
+
+               // Extract the code nodes from the docs
+               void GetExamples (XElement n, StringBuilder sb)
+               {
+                       foreach (var code in n.Descendants ("code"))
+                               sb.Append ((string)code);
+               }
+
+               // Extract a large name for the Node
+               static string LargeName (Node matched_node)
+               {
+                       string[] parts = matched_node.GetInternalUrl ().Split('/', '#');
+                       if (parts.Length == 3 && parts[2] != String.Empty) //List of Members, properties, events, ...
+                               return parts[1] + ": " + matched_node.Caption;
+                       else if(parts.Length >= 4) //Showing a concrete Member, property, ...
+                               return parts[1] + "." + matched_node.Caption;
+                       else
+                               return matched_node.Caption;
+               }
+
+               XElement GetMemberFromCaption (XDocument xdoc, string caption, bool isOperator, ILookup<string, XElement> prematchedMembers)
+               {
+                       string name;
+                       IList<string> args;
+                       var doc = xdoc.Root.Element ("Members").Elements ("Member");
+
+                       if (isOperator) {
+                               // The first case are explicit and implicit conversion operators which are grouped specifically
+                               if (caption.IndexOf (" to ") != -1) {
+                                       var convArgs = caption.Split (new[] { " to " }, StringSplitOptions.None);
+                                       return doc
+                                               .First (n => (AttrEq (n, "MemberName", "op_Explicit") || AttrEq (n, "MemberName", "op_Implicit"))
+                                                       && ((string)n.Element ("ReturnValue").Element ("ReturnType")).Equals (convArgs[1], StringComparison.Ordinal)
+                                                       && AttrEq (n.Element ("Parameters").Element ("Parameter"), "Type", convArgs[0]));
+                               } else {
+                                       return doc.First (m => AttrEq (m, "MemberName", "op_" + caption));
+                               }
+                       }
+
+                       TryParseCaption (caption, out name, out args);
+
+                       if (!string.IsNullOrEmpty (name)) { // Filter member by name
+                               var prematched = prematchedMembers[name];
+                               doc = prematched.Any () ? prematched : doc.Where (m => AttrEq (m, "MemberName", name));
+                       }
+                       if (args != null && args.Count > 0) // Filter member by its argument list
+                               doc = doc.Where (m => m.Element ("Parameters").Elements ("Parameter").Attributes ("Type").Select (a => (string)a).SequenceEqual (args));
+
+                       return doc.First ();
+               }
+
+               XElement GetDocsFromCaption (XDocument xdoc, string caption, bool isOperator, ILookup<string, XElement> prematchedMembers)
+               {
+                       return GetMemberFromCaption (xdoc, caption, isOperator, prematchedMembers).Element ("Docs");
+               }
+
+               // A simple stack-based parser to detect single type definition separated by commas
+               IEnumerable<string> ExtractArguments (string rawArgList)
+               {
+                       var sb = new System.Text.StringBuilder ();
+                       int genericDepth = 0;
+                       int arrayDepth = 0;
+
+                       for (int i = 0; i < rawArgList.Length; i++) {
+                               char c = rawArgList[i];
+                               switch (c) {
+                               case ',':
+                                       if (genericDepth == 0 && arrayDepth == 0) {
+                                               yield return sb.ToString ();
+                                               sb.Clear ();
+                                               continue;
+                                       }
+                                       break;
+                               case '<':
+                                       genericDepth++;
+                                       break;
+                               case '>':
+                                       genericDepth--;
+                                       break;
+                               case '[':
+                                       arrayDepth++;
+                                       break;
+                               case ']':
+                                       arrayDepth--;
+                                       break;
+                               }
+                               sb.Append (c);
+                       }
+                       if (sb.Length > 0)
+                               yield return sb.ToString ();
+               }
+
+               void TryParseCaption (string caption, out string name, out IList<string> argList)
+               {
+                       name = null;
+                       argList = null;
+                       int parenIdx = caption.IndexOf ('(');
+                       // In case of simple name, there is no need for processing
+                       if (parenIdx == -1) {
+                               name = caption;
+                               return;
+                       }
+                       name = caption.Substring (0, parenIdx);
+                       // Now we gather the argument list if there is any
+                       var rawArgList = caption.Substring (parenIdx + 1, caption.Length - parenIdx - 2); // Only take what's inside the parens
+                       if (string.IsNullOrEmpty (rawArgList))
+                               return;
+
+                       argList = ExtractArguments (rawArgList).Select (arg => arg.Trim ()).ToList ();
+               }
+
+               bool AttrEq (XElement element, string attributeName, string expectedValue)
+               {
+                       return ((string)element.Attribute (attributeName)).Equals (expectedValue, StringComparison.Ordinal);
+               }
+       }
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/providers/ecmaspec-provider.cs b/mcs/tools/monkeydoc/MonkeyDoc/providers/ecmaspec-provider.cs
new file mode 100644 (file)
index 0000000..6b4c050
--- /dev/null
@@ -0,0 +1,194 @@
+//
+// The ecmaspec provider is for ECMA specifications
+//
+// Authors:
+//     John Luke (jluke@cfl.rr.com)
+//     Ben Maurer (bmaurer@users.sourceforge.net)
+//
+// Use like this:
+//   mono assembler.exe --ecmaspec DIRECTORY --out name
+//
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+using System.Xml;
+using System.Collections.Generic;
+using Lucene.Net.Index;
+using Lucene.Net.Documents;
+
+namespace MonkeyDoc.Providers
+{
+       public class EcmaSpecProvider : Provider
+       {
+               string basedir;
+       
+               public EcmaSpecProvider (string base_directory)
+               {
+                       basedir = base_directory;
+                       if (!Directory.Exists (basedir))
+                               throw new DirectoryNotFoundException (String.Format ("The directory `{0}' does not exist", basedir));
+               }
+       
+               public override void PopulateTree (Tree tree)
+               {
+                       XPathNavigator n = new XPathDocument (Path.Combine (basedir, "toc.xml")).CreateNavigator ();
+                       n.MoveToRoot ();
+                       n.MoveToFirstChild ();
+                       PopulateNode (n.SelectChildren ("node", ""), tree.RootNode);
+               }
+       
+               void PopulateNode (XPathNodeIterator nodes, Node treeNode)
+               {
+                       foreach (XPathNavigator n in nodes) {
+                               string secNumber = n.GetAttribute ("number", "");
+                               string secName = n.GetAttribute ("name", "");
+
+                               var storage = treeNode.Tree.HelpSource.Storage;
+                               using (var file = File.OpenRead (Path.Combine (basedir, secNumber + ".xml")))
+                                       storage.Store (secNumber, file);
+
+                               Node thisNode = treeNode.GetOrCreateNode (secNumber + ": " + secName, "ecmaspec:" + secNumber);
+                       
+                               if (n.HasChildren)
+                                       PopulateNode (n.SelectChildren ("node", ""), thisNode);
+                       }
+               }
+
+               public override void CloseTree (HelpSource hs, Tree tree)
+               {
+               }
+       }
+
+       public class EcmaSpecHelpSource : HelpSource
+       {
+               const string EcmaspecPrefix = "ecmaspec:";
+               const string TocPart = "%toc"; // What is returned as TocXml
+               const string SpecPart = "%spec"; // What is returned as Ecmaspec
+
+               public EcmaSpecHelpSource (string base_file, bool create) : base (base_file, create)
+               {
+               }
+
+               public override DocumentType GetDocumentTypeForId (string id, out Dictionary<string, string> extraParams)
+               {
+                       extraParams = null;
+                       return id.EndsWith (TocPart) ? DocumentType.TocXml : DocumentType.EcmaSpecXml;
+               }
+
+               public override bool IsGeneratedContent (string id)
+               {
+                       return id == "root:" || id.EndsWith (TocPart);
+               }
+
+               public override bool IsMultiPart (string id, out IEnumerable<string> parts)
+               {
+                       if (id == "root:" || id.EndsWith (TocPart) || id.EndsWith (SpecPart)) {
+                               parts = null;
+                               return false;
+                       }
+                       parts = MakeMultiPart (id);
+                       return true;
+               }
+
+               IEnumerable<string> MakeMultiPart (string baseId)
+               {
+                       yield return baseId + SpecPart;
+                       yield return baseId + TocPart;
+               }
+
+               public override string GetText (string id)
+               {
+                       Node n = id == "root:" ? Tree.RootNode : MatchNode (EcmaspecPrefix + id.Substring (0, id.Length - TocPart.Length));
+                       if (n == null)
+                               throw new ArgumentException ("id", string.Format ("{0} -> {1}", id, EcmaspecPrefix + id.Substring (0, id.Length - TocPart.Length)));
+                       return TreeDumper.ExportToTocXml (n, "C# Language Specification", "In this section:");
+               }
+
+               public override Stream GetHelpStream (string id)
+               {
+                       return id.EndsWith (SpecPart) ? base.GetHelpStream (id.Substring (0, id.IndexOf (SpecPart))) : base.GetHelpStream (id);
+               }
+       
+               public override void PopulateSearchableIndex (IndexWriter writer) 
+               {
+                       foreach (Node n in Tree.RootNode.Nodes)
+                               AddDocuments (writer, n);
+               }
+
+               protected override string UriPrefix {
+                       get {
+                               return EcmaspecPrefix;
+                       }
+               }
+
+               void AddDocuments (IndexWriter writer, Node node) 
+               {
+                       string url = node.PublicUrl;
+                       Stream file_stream = GetHelpStream (url.Substring (9));
+                       if (file_stream == null) //Error
+                               return;
+                       XmlDocument xdoc = new XmlDocument ();
+                       xdoc.Load (new XmlTextReader (file_stream));
+
+                       //Obtain the title
+                       XmlNode nelem = xdoc.DocumentElement;
+                       string title = nelem.Attributes["number"].Value + ": " + nelem.Attributes["title"].Value;
+
+                       //Obtain the text
+                       StringBuilder s = new StringBuilder ();
+                       GetTextNode (nelem, s);
+                       string text = s.ToString ();
+
+                       //Obtain the examples
+                       StringBuilder s2 = new StringBuilder ();
+                       GetExamples (nelem, s2);
+                       string examples = s2.ToString ();
+
+                       //Write to the Lucene Index all the parts
+                       SearchableDocument doc = new SearchableDocument ();
+                       doc.Title = title;
+                       doc.HotText = title.Substring (title.IndexOf (':')); 
+                       doc.Url = url;
+                       doc.Text = text;
+                       doc.Examples = examples;
+                       writer.AddDocument (doc.LuceneDoc);
+               
+                       if (node.IsLeaf)
+                               return;
+
+                       foreach (Node n in node.Nodes)
+                               AddDocuments (writer, n);
+               }
+
+               void GetTextNode (XmlNode n, StringBuilder s) 
+               {
+                       //dont include c# code
+                       if (n.Name == "code_example")
+                               return;
+                       //include all text from nodes
+                       if (n.NodeType == XmlNodeType.Text)
+                               s.Append (n.Value);
+               
+                       //recursively explore all nodes
+                       if (n.HasChildNodes)
+                               foreach (XmlNode n_child in n.ChildNodes)
+                                       GetTextNode (n_child, s);
+               }
+
+               void GetExamples (XmlNode n, StringBuilder s)
+               {
+                       if (n.Name == "code_example") {
+                               if (n.FirstChild.Name == "#cdata-section")
+                                       s.Append (n.FirstChild.Value);
+                       } else {
+                               if (n.HasChildNodes)
+                                       foreach (XmlNode n_child in n.ChildNodes)
+                                               GetExamples (n_child, s);
+                       }
+               }
+       }
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/providers/ecmauncompiled-provider.cs b/mcs/tools/monkeydoc/MonkeyDoc/providers/ecmauncompiled-provider.cs
new file mode 100644 (file)
index 0000000..272eb64
--- /dev/null
@@ -0,0 +1,62 @@
+using System;
+using System.Linq;
+using System.IO;
+using System.Text;
+using System.Xml;
+using System.Xml.Linq;
+using System.Collections.Generic;
+
+using Lucene.Net.Index;
+using Lucene.Net.Documents;
+
+using MonkeyDoc.Ecma;
+using MonkeyDoc.Storage;
+using Mono.Utilities;
+
+namespace MonkeyDoc.Providers
+{
+       public class EcmaUncompiledHelpSource : EcmaHelpSource
+       {
+               readonly DirectoryInfo basedir;
+               readonly string basedoc;
+
+               public readonly string BasePath;
+
+               public new string Name {
+                       get;
+                       private set;
+               }
+       
+               /* base_file: the directory containing the index.xml file, usually in Mono land .../Documentation/en
+                * markName: if true, we encase the node caption with [] to clearly mark it's from an uncompiled source
+                */
+               public EcmaUncompiledHelpSource (string base_file, bool markName = true) : base ()
+               {
+                       basedir = new DirectoryInfo (base_file);
+                       BasePath = basedir.FullName;
+               
+                       basedoc = Path.Combine (basedir.FullName, "index.xml");
+               
+                       Name = ((string)XDocument.Load (basedoc).Root.Element ("Title")) ?? "UnnamedUncompiledSource";
+                       if (markName)
+                               Name = '[' + Name + ']';
+                       Tree.RootNode.Caption = Name;
+
+                       Func<XElement, string> indexGenerator = type => {
+                               var nsName = (string)type.Parent.Attribute ("Name");
+                               var typeName = (string)type.Attribute ("Name");
+                               return Path.ChangeExtension (nsName + '/' + typeName, ".xml");
+                       };
+
+                       this.Storage = new UncompiledDocStorage (BasePath);
+
+                       EcmaDoc.PopulateTreeFromIndexFile (basedoc, Tree, null, null);
+               }
+
+               protected override string UriPrefix {
+                       get {
+                               return "uncompiled:";
+                       }
+               }
+       }
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/providers/error-provider.cs b/mcs/tools/monkeydoc/MonkeyDoc/providers/error-provider.cs
new file mode 100644 (file)
index 0000000..2acb26e
--- /dev/null
@@ -0,0 +1,201 @@
+//
+// error-provider.cs
+//
+// Author:
+//   Ben Maurer (bmaurer@users.sourceforge.net)
+//
+// (C) 2003 Ben Maurer
+// Copyright 2003-2011 Novell
+// Copyright 2011 Xamarin Inc
+//
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using System.Xml.Serialization;
+using System.Linq;
+using Lucene.Net.Index;
+using Lucene.Net.Documents;
+
+namespace MonkeyDoc.Providers
+{
+       public class ErrorProviderConfig
+       {
+               public string FilesPath;
+               public string Match;
+               public int ErrorNumSubstringStart;
+               public int ErrorNumSubstringLength;
+               public string FriendlyFormatString;
+
+               public override string ToString ()
+               {
+                       var sb = new StringBuilder ();
+                       var w = new StringWriter (sb);
+                       
+                       w.WriteLine ("FilesPath: {0}", FilesPath);
+                       w.WriteLine ("Match: {0}", Match);
+                       w.WriteLine ("Error Number Substring: {0} Length:{1}", ErrorNumSubstringStart, ErrorNumSubstringLength);
+                       w.WriteLine ("FriendlyFormatString: {0}", FriendlyFormatString);
+                       
+                       return w.ToString ();
+               }
+               
+               public Dictionary<string, ErrorDocumentation> Compile (HelpSource hs)
+               {
+                       string[] files = Directory.GetFiles (FilesPath, Match);
+                       var ret = new Dictionary<string, ErrorDocumentation> ();
+                       
+                       foreach (string s in files) {
+                               ErrorDocumentation d;
+                               int errorNum = 0;
+
+                               try {
+                                       errorNum = int.Parse (Path.GetFileName (s).Substring (ErrorNumSubstringStart, ErrorNumSubstringLength));
+                               } catch {
+                                       Console.WriteLine ("Ignoring file {0}", s);
+                               }
+                               
+                               string errorName = String.Format (FriendlyFormatString, errorNum);
+                               
+                               if (!ret.TryGetValue (errorName, out d))
+                                       ret[errorName] = d = new ErrorDocumentation (errorName);
+
+                               if (d.Details == null) {
+                                       string xmlFile = Path.ChangeExtension (s, "xml");
+                                       if (File.Exists (xmlFile)) {
+                                               XmlSerializer cfgRdr = new XmlSerializer (typeof (ErrorDetails));
+                                               d.Details = (ErrorDetails)cfgRdr.Deserialize (new XmlTextReader (xmlFile));
+                                       }
+                               }
+                               // Encoding is same as used in MCS, so we will be able to do all those files
+                               using (StreamReader reader = new StreamReader (s, Encoding.GetEncoding (28591))) {
+                                       d.Examples.Add (reader.ReadToEnd ());
+                               }
+                       }
+                       
+                       return ret;
+               }
+       }
+
+       public class ErrorDocumentation
+       {
+               public string ErrorName;
+               public ErrorDetails Details;
+               public List<string> Examples = new List<string> ();
+               
+               public ErrorDocumentation () {}
+               public ErrorDocumentation (string ErrorName)
+               {
+                       this.ErrorName = ErrorName;
+               }
+       }
+       
+       public class ErrorDetails
+       {
+               public XmlNode Summary;
+               public XmlNode Details;
+       }
+
+       public class ErrorProvider : Provider
+       {
+               ErrorProviderConfig config;
+               
+               public ErrorProvider (string configFile)
+               {
+                       config = ReadConfig (configFile);
+               }
+               
+               public static ErrorProviderConfig ReadConfig (string file)
+               {
+                       XmlSerializer cfgRdr = new XmlSerializer (typeof (ErrorProviderConfig));
+                       ErrorProviderConfig ret = (ErrorProviderConfig)cfgRdr.Deserialize (new XmlTextReader (file));
+                       // handle path rel to the config file
+                       ret.FilesPath = Path.Combine (Path.GetDirectoryName (file), ret.FilesPath);
+                       return ret;
+               }
+       
+               public override void PopulateTree (Tree tree)
+               {
+                       // everything is done in CloseTree so we can pack
+               }
+       
+               public override void CloseTree (HelpSource hs, Tree tree)
+               {
+                       var entries = config.Compile (hs);
+                       MemoryStream ms = new MemoryStream ();
+                       XmlSerializer writer = new XmlSerializer (typeof (ErrorDocumentation));
+                       
+                       foreach (var de in entries) {
+                               ErrorDocumentation d = de.Value;
+                               string s = de.Key;
+
+                               tree.RootNode.GetOrCreateNode (s, "error:" + s);
+                               
+                               writer.Serialize (ms, d);
+                               ms.Position = 0;
+                               hs.Storage.Store (s, ms);
+                               ms.SetLength (0);
+                       }
+                       
+                       tree.RootNode.Sort ();
+               }
+       }
+       
+       public class ErrorHelpSource : HelpSource
+       {               
+               public ErrorHelpSource (string base_file, bool create) : base (base_file, create)
+               {
+               }
+
+               public override string GetText (string id)
+               {
+                       return TreeDumper.ExportToTocXml (Tree.RootNode, "Compiler Error Reference", "In this section:");
+               }
+               
+               protected override string UriPrefix {
+                       get {
+                               return "error:";
+                       }
+               }
+
+               public override bool IsGeneratedContent (string id)
+               {
+                       return id == "root:";
+               }
+
+               public override DocumentType GetDocumentTypeForId (string id, out Dictionary<string, string> extraParams)
+               {
+                       extraParams = null;
+                       return id == "root:" ? DocumentType.TocXml : DocumentType.ErrorXml;
+               }
+
+               public override string GetInternalIdForUrl (string url, out Node node)
+               {
+                       var result = base.GetInternalIdForUrl (url, out node);
+                       return result.ToLower ();
+               }
+               
+               public override void PopulateIndex (IndexMaker index_maker)
+               {
+                       foreach (Node n in Tree.RootNode.Nodes)
+                               index_maker.Add (n.Caption, n.Caption, n.Element);
+               }
+
+               public override void PopulateSearchableIndex (IndexWriter writer) 
+               {
+                       foreach (Node n in Tree.RootNode.Nodes) {
+                               XmlSerializer reader = new XmlSerializer (typeof (ErrorDocumentation));
+                               ErrorDocumentation d = (ErrorDocumentation)reader.Deserialize (GetHelpStream (n.Element.Substring (6)));
+                               SearchableDocument doc = new SearchableDocument ();
+                               doc.Title = d.ErrorName;
+                               doc.Url = n.Element;
+                               doc.Text = d.Details != null ? d.Details.ToString () : string.Empty;
+                               doc.Examples = d.Examples.Cast<string> ().Aggregate ((e1, e2) => e1 + Environment.NewLine + e2);
+                               doc.HotText = d.ErrorName;
+                               writer.AddDocument (doc.LuceneDoc);
+                       }
+               }
+       }
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/providers/man-provider.cs b/mcs/tools/monkeydoc/MonkeyDoc/providers/man-provider.cs
new file mode 100755 (executable)
index 0000000..32b9c93
--- /dev/null
@@ -0,0 +1,106 @@
+//
+// A provider to display man pages
+//
+// Authors:
+//   Johannes Roith <johannes@roith.de>
+//   Jonathan Pryor <jpryor@novell.com>
+//
+// (C) 2008 Novell, Inc.
+
+using System;
+using System.IO;
+using System.Text;
+using System.Xml;
+using System.Linq;
+using System.Collections.Generic;
+
+namespace MonkeyDoc.Providers
+{
+       public class ManProvider : Provider
+       {
+               string[] tocFiles;
+       
+               public ManProvider (string[] handbookTocFiles)
+               {
+                       tocFiles = handbookTocFiles;
+
+                       // huh...
+                       if (!File.Exists (tocFiles[0]))
+                               throw new FileNotFoundException (String.Format ("The table of contents, `{0}' does not exist", tocFiles[0]));
+               }
+
+               public override void PopulateTree (Tree tree)
+               {
+                       foreach(string TocFile in tocFiles) {
+                               XmlDocument doc = new XmlDocument();
+                               doc.Load (TocFile);
+
+                               XmlNodeList nodeList = doc.GetElementsByTagName("manpage");
+                               Node nodeToAddChildrenTo = tree.RootNode;
+                               var storage = nodeToAddChildrenTo.Tree.HelpSource.Storage;
+
+                               foreach (XmlNode node in nodeList) {
+
+                                       XmlAttribute name = node.Attributes["name"];
+                                       XmlAttribute page = node.Attributes["page"];
+
+                                       if (name == null || page == null) continue;
+
+                                       if (!File.Exists (page.Value))
+                                               continue;
+
+                                       string target = "man:" + name.Value;
+                                       nodeToAddChildrenTo.CreateNode (name.Value, target);
+
+                                       if (File.Exists (page.Value))
+                                               storage.Store (name.Value, File.OpenRead (page.Value));
+                               }
+                       }
+               }
+
+               public override void CloseTree (HelpSource hs, Tree tree)
+               {
+               }
+       }
+
+       public class ManHelpSource : HelpSource
+       {
+               const string ManPrefix = "man:";
+               Dictionary<string, Node> nodesMap;
+
+               public ManHelpSource (string base_file, bool create) : base (base_file, create)
+               {
+                       nodesMap = Tree.RootNode.Nodes.ToDictionary (n => n.Element);
+               }
+
+               // Since man always has a flat tree and rather small amount of item
+               // we store them in a dictionary
+               public override Node MatchNode (string url)
+               {
+                       Node result;
+                       return nodesMap.TryGetValue (url, out result) ? result : null;
+               }
+
+               public override DocumentType GetDocumentTypeForId (string id, out Dictionary<string, string> extraParams)
+               {
+                       extraParams = null;
+                       return id == "root:" ? DocumentType.TocXml : DocumentType.Man;
+               }
+
+               public override bool IsGeneratedContent (string id)
+               {
+                       return id == "root:";
+               }
+       
+               public override string GetText (string url)
+               {
+                       return TreeDumper.ExportToTocXml (Tree.RootNode, "Mono Documentation Library", "Available man pages:");
+               }
+
+               protected override string UriPrefix {
+                       get {
+                               return ManPrefix;
+                       }
+               }
+       }
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/providers/simple-provider.cs b/mcs/tools/monkeydoc/MonkeyDoc/providers/simple-provider.cs
new file mode 100644 (file)
index 0000000..e567dc1
--- /dev/null
@@ -0,0 +1,153 @@
+//
+// The simple provider is an example provider
+//
+// Author:
+//   Miguel de Icaza (miguel@ximian.com)
+//
+// Use like this:
+//   mono assembler.exe --simple DIRECTORY --out name
+//
+// Then create a .source file in your sources directory, and copy
+// name.tree and name.zip to the sources directory.
+//
+// To view the tree generated, use:
+//   mono dump.exe name.tree
+//
+namespace Monodoc {
+using System;
+using System.IO;
+using System.Text;
+
+//
+// The simple provider generates the information source
+//
+public class SimpleProvider : Provider {
+       string basedir;
+       
+       public SimpleProvider (string base_directory)
+       {
+               basedir = base_directory;
+               if (!Directory.Exists (basedir))
+                       throw new FileNotFoundException (String.Format ("The directory `{0}' does not exist", basedir));
+       }
+
+       public override void PopulateTree (Tree tree)
+       {
+               Node top = tree.LookupNode ("Directory at: " + basedir, "simple:");
+               
+               foreach (string dir in Directory.GetDirectories (basedir)){
+                       string url = Path.GetFileName (dir);
+                       Node n = top.LookupNode ("Dir: " + url, url);
+                       PopulateDir (n, dir);
+               }
+       }
+
+#pragma warning disable 219
+       void PopulateDir (Node me, string dir)
+       {
+               Console.WriteLine ("Adding: " + dir);
+               foreach (string child_dir in Directory.GetDirectories (dir)){
+                       string url = Path.GetFileName (child_dir);
+                       Node n = me.LookupNode ("Dir: " + url, "simple-directory:" + url);
+                       PopulateDir (me, child_dir);
+               }
+
+               foreach (string file in Directory.GetFiles (dir)){
+                       Console.WriteLine ("   File: " + file);
+                       string file_code = me.tree.HelpSource.PackFile (file);
+
+                       //
+                       // The url element encoded for the file is:
+                       //  originalfilename#CODE
+                       //
+                       // The code is assigned to us after the file has been packaged
+                       // We use the original-filename later to render html or text files
+                       //
+                       Node n = me.LookupNode (Path.GetFileName (file), file + "#" + file_code);
+                       
+               }
+       }
+
+       public override void CloseTree (HelpSource hs, Tree tree)
+       {
+       }
+}
+
+//
+// The HelpSource is used during the rendering phase.
+//
+
+public class SimpleHelpSource : HelpSource {
+       Encoding enc;
+       
+       public SimpleHelpSource (string base_file, bool create) : base (base_file, create)
+       {
+               enc = new UTF8Encoding (false, false);
+       }
+
+       public override string GetText (string url, out Node match_node)
+       {
+               match_node = null;
+
+               string c = GetCachedText (url);
+               if (c != null)
+                       return c;
+
+               if (url.StartsWith ("simple:") || url.StartsWith ("simple-directory:"))
+                       return GetTextFromUrl (url);
+
+               return null;
+       }
+
+       string GetTextFromUrl (string url)
+       {
+               // Remove "simple:" prefix
+               url = url.Substring (7);
+
+               if (url.StartsWith ("simple-directory:"))
+                       return String.Format ("<html>This is a directory entry point: {0} </html>",
+                                             url.Substring (17));
+
+               // Otherwise the last element of the url is the file code we got.
+               int pound = url.LastIndexOf ("#");
+               string code;
+               if (pound == -1)
+                       code = url;
+               else
+                       code = url.Substring (pound+1);
+
+
+               Stream s = GetHelpStream (code);
+               if (s == null)
+                       return String.Format ("<html>No stream for this node: {0} </html>", url);
+
+               //
+               // Now, get the file type
+               //
+               int slash = url.LastIndexOf ("/");
+               string fname = url.Substring (slash + 1, pound - slash - 1).ToLower ();
+
+               if (fname.EndsWith (".html") || fname.EndsWith (".htm")){
+                       TextReader r = new StreamReader (s, enc);
+                       return r.ReadToEnd ();
+               }
+
+               if (fname.EndsWith (".png") || fname.EndsWith (".jpg") ||
+                   fname.EndsWith (".jpeg") || fname.EndsWith (".gif")){
+                       return "<html>Image file, have not implemented rendering this yet</html>";
+               }
+
+               // Convert text to HTML
+               StringBuilder result = new StringBuilder ("<html>");
+               TextReader reader = new StreamReader (s, enc);
+               string line;
+               
+               while ((line = reader.ReadLine ()) != null){
+                       result.Append (line);
+                       result.Append ("<br>");
+               }
+               result.Append ("<html>");
+               return result.ToString ();
+       }
+}
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/providers/xhtml-provider.cs b/mcs/tools/monkeydoc/MonkeyDoc/providers/xhtml-provider.cs
new file mode 100644 (file)
index 0000000..9e7c0f2
--- /dev/null
@@ -0,0 +1,197 @@
+//
+// A provider that uses Windows help file xhtml TOC files and looks for the
+// referenced documents to create the help source. 
+//
+// Authors:
+// Copyright 2003 Lee Mallabone <gnome@fonicmonkey.net>
+//   Johannes Roith <johannes@roith.de>
+//   Miguel de Icaza <miguel@ximian.com>
+
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Xml;
+
+namespace MonkeyDoc.Providers
+{
+       public class XhtmlProvider : Provider
+       {
+               string tocFile;
+       
+               public XhtmlProvider (string handbookTocFile)
+               {
+                       tocFile = handbookTocFile;
+                       if (!File.Exists (tocFile))
+                               throw new FileNotFoundException (String.Format ("The table of contents, `{0}' does not exist", tocFile));               
+               }
+
+               public override void PopulateTree (Tree tree)
+               {
+                       //new SimpleHandbookTOCParser(tree, tocFile);
+                       // TODO: port it
+               }
+
+               public override void CloseTree (HelpSource hs, Tree tree)
+               {
+               }
+       }
+
+       public class XhtmlHelpSource : HelpSource
+       {
+               public XhtmlHelpSource (string base_file, bool create) : base (base_file, create)
+               {
+
+               }
+
+               const string XhtmlPrefix = "xhtml:";
+
+               protected override string UriPrefix {
+                       get {
+                               return XhtmlPrefix;
+                       }
+               }
+               
+               public override DocumentType GetDocumentTypeForId (string id, out Dictionary<string, string> extraArgs)
+               {
+                       extraArgs = null;
+                       return id == "root:" ? DocumentType.TocXml : DocumentType.MonoBook;
+               }
+
+               public override bool IsGeneratedContent (string id)
+               {
+                       return id == "root:";
+               }
+       
+               public override string GetText (string url)
+               {
+                       return TreeDumper.ExportToTocXml (Tree.RootNode, "Mono Handbook", string.Empty);
+               }
+
+               public static string GetAbsoluteLink(string target, string url)
+               {
+                       
+                       string value = null;
+               
+                       if (target.StartsWith ("#") ||
+                           target.StartsWith ("T:") ||
+                           target.StartsWith ("M:") ||
+                           target.StartsWith ("P:") ||
+                           target.StartsWith ("T:") ||
+                           target.StartsWith ("E:") ||
+                           target.StartsWith ("F:") ||
+                           target.StartsWith ("O:") ||
+                           target.StartsWith ("N:") ||
+                           target.StartsWith ("api:"))
+                               return null;
+               
+                       int endp = target.IndexOf(':');
+               
+                       if (endp == -1)
+                               endp = 0;
+                       string protocol = target.Substring(0, endp);
+                       switch (protocol) {
+                       case "mailto": 
+                       case "http":
+                       case "https":
+                       case "ftp":
+                       case "news":
+                       case "irc":
+                               break;
+                       default:
+                               // handle absolute urls like: /html/en/images/empty.png
+                               if (!target.StartsWith("/")) {
+                               
+                                       // url is something like "gnome/bindings/mono.html"
+                                       // This will get the path "gnome/bindings"
+                               
+                                       int slash = url.LastIndexOf ("/");
+                                       string tmpurl = url;
+                               
+                                       if (slash != -1)
+                                               tmpurl  = url.Substring(0, slash);
+                               
+                                       // Count "../" in target and go one level down
+                                       // for each in tmpurl, eventually, then remove "../".
+                               
+                                       Regex reg1 = new Regex("../");
+                                       MatchCollection matches = reg1.Matches(target);
+                               
+                                       for(int i = 1; i < matches.Count; i++) {
+                                               slash = tmpurl.LastIndexOf ("/");
+                                               if (slash != -1) 
+                                                       tmpurl  = tmpurl.Substring(0, slash);
+                                       }
+                               
+                                       target = target.Replace("../", "");
+                               
+                                       value = tmpurl + "/" + target;
+                               
+                               } else {
+                                       value = target.Substring(1, target.Length - 1);
+                               }
+                               break;
+                       }
+                       return value;
+               }
+       
+               XmlDocument RewriteLinks(XmlDocument docToProcess, string url)
+               {
+                       XmlNodeList nodeList = docToProcess.GetElementsByTagName("a");
+               
+                       foreach(XmlNode node in nodeList) {
+                       
+                               XmlElement element = (XmlElement) node;
+                       
+                               if (element.HasAttribute("href") ){
+                               
+                                       XmlAttribute href = element.GetAttributeNode("href");
+                                       string target = href.Value;
+                               
+                                       target = GetAbsoluteLink(target, url);
+                                       if (target != null) {
+                                               string newtarget = String.Format ("source-id:{0}:xhtml:{1}", SourceID, target);
+                                               href.Value = newtarget;
+                                       }
+                               }
+                       }
+
+                       nodeList = docToProcess.GetElementsByTagName("img");
+
+                       foreach(XmlNode node in nodeList) {
+                                                                                                                                    
+                               XmlElement element = (XmlElement) node;
+                                                                                                                                    
+                               if (element.HasAttribute("src") ){
+                                                                                                                                    
+                                       XmlAttribute href = element.GetAttributeNode("src");
+                                       string target = href.Value;
+                                                                                                                                    
+                                       target = GetAbsoluteLink(target, url);
+                                       if (target != null) {
+                                               string newtarget = String.Format ("source-id:{0}:xhtml:{1}", SourceID, target);
+                                               href.Value = newtarget;
+                                       }
+                               }               
+                       }
+
+                       return docToProcess;
+               }
+
+               public override void PopulateIndex (IndexMaker index_maker)
+               {
+                       PopulateIndexFromNodes (Tree.RootNode);
+               }
+
+               void PopulateIndexFromNodes (Node start)
+               {
+                       /*var nodes = start.Nodes;
+               
+                       if (nodes != null) {
+                               foreach (Node n in nodes)
+                                       PopulateIndexFromNodes (n);
+                       }*/
+               }
+       }
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/settings.cs b/mcs/tools/monkeydoc/MonkeyDoc/settings.cs
new file mode 100644 (file)
index 0000000..ad73e42
--- /dev/null
@@ -0,0 +1,47 @@
+using System;
+using System.Configuration;
+using System.Collections.Specialized;
+
+namespace MonkeyDoc
+{
+       public static class Settings
+       {
+               static KeyValueConfigurationCollection libConfig;
+               static KeyValueConfigurationCollection exeConfig;
+
+               static Settings ()
+               {
+                       try {
+                               var config = ConfigurationManager.OpenExeConfiguration (System.Reflection.Assembly.GetExecutingAssembly ().Location);
+                               libConfig = config.AppSettings.Settings;
+                       } catch {}
+
+                       try {
+                               exeConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).AppSettings.Settings;
+                       } catch {}
+               }
+
+               public static string Get (string key) {
+                       KeyValueConfigurationElement element = null;
+                       // We check the configuration in order: app first and then library itself
+                       if (exeConfig != null)
+                               element = exeConfig[key];
+                       if (element == null && libConfig != null)
+                               element = libConfig[key];
+
+                       return element == null ? null : element.Value;
+               }
+
+               public static KeyValueConfigurationCollection AppSettings {
+                       get {
+                               return exeConfig;
+                       }
+               }
+
+               public static KeyValueConfigurationCollection LibSettings {
+                       get {
+                               return libConfig;
+                       }
+               }
+       }
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/storage.cs b/mcs/tools/monkeydoc/MonkeyDoc/storage.cs
new file mode 100644 (file)
index 0000000..9085ff5
--- /dev/null
@@ -0,0 +1,53 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+
+namespace MonkeyDoc
+{
+       // Define a storage mechanism for a help source
+       public interface IDocStorage : IDisposable
+       {
+               // Tell if the storage can store successive change to the doc as revision
+               bool SupportRevision { get; }
+               IDocRevisionManager RevisionManager { get; }
+
+               // Tell if the storage support modifying an existing data
+               bool SupportChange { get; }
+
+               /* Store data inside the storage backend
+                * if SupportChange is false and user try to store something with an existing id
+                * an exception will be thrown
+                * if id is null or empty, the storage will try to create an automatic id. In all
+                * case the id that has been used to store the content is returned by the method
+                */
+               string Store (string id, string text);
+               string Store (string id, byte[] data);
+               string Store (string id, Stream stream);
+
+               Stream Retrieve (string id);
+
+               IEnumerable<string> GetAvailableIds ();
+       }
+
+       public interface IDocRevisionManager
+       {
+               Stream RetrieveWithRevision (string id, string revision);
+
+               // This should be ordered by most recent first
+               IEnumerable<string> AvailableRevisionsForId (string id);
+               // This can simply be implemented with above property but it can also be
+               // a revision storage symbolic value like "HEAD"
+               string LatestRevisionForId (string id);
+
+               // A commit message for instance
+               string GetRevisionDescription (string revision);
+       }
+
+       public static class DocRevisionManagerExtensions
+       {
+               public static Stream RetrieveLatestRevision (this IDocRevisionManager revManager, string id)
+               {
+                       return revManager.RetrieveWithRevision (id, revManager.LatestRevisionForId (id));
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/storage/NullStorage.cs b/mcs/tools/monkeydoc/MonkeyDoc/storage/NullStorage.cs
new file mode 100644 (file)
index 0000000..891a965
--- /dev/null
@@ -0,0 +1,63 @@
+using System;
+using System.IO;
+using System.Xml;
+using System.Linq;
+using System.Collections.Generic;
+
+namespace MonkeyDoc.Storage
+{
+       // A storage that doesn't store
+       public class NullStorage : IDocStorage
+       {
+               public NullStorage ()
+               {
+               }
+
+               public bool SupportRevision {
+                       get {
+                               return false;
+                       }
+               }
+
+               public IDocRevisionManager RevisionManager {
+                       get {
+                               return null;
+                       }
+               }
+
+               public bool SupportChange {
+                       get {
+                               return true;
+                       }
+               }
+
+               public string Store (string id, string text)
+               {
+                       return id;
+               }
+
+               public string Store (string id, byte[] data)
+               {
+                       return id;
+               }
+
+               public string Store (string id, Stream stream)
+               {
+                       return id;
+               }
+
+               public Stream Retrieve (string id)
+               {
+                       return null;
+               }
+
+               public IEnumerable<string> GetAvailableIds ()
+               {
+                       return Enumerable.Empty<string> (); 
+               }
+
+               public void Dispose ()
+               {
+               }
+       }
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/storage/UncompiledDocStorage.cs b/mcs/tools/monkeydoc/MonkeyDoc/storage/UncompiledDocStorage.cs
new file mode 100644 (file)
index 0000000..fe3976a
--- /dev/null
@@ -0,0 +1,69 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Collections.Generic;
+
+namespace MonkeyDoc.Storage
+{
+       // A read-only storage to access ecma XML document based on a standard directory layout
+       // id are relative path inside the base doc directory
+       public class UncompiledDocStorage : IDocStorage
+       {
+               readonly string basePath;
+
+               public UncompiledDocStorage (string basePath)
+               {
+                       this.basePath = basePath;
+               }
+
+               public bool SupportRevision {
+                       get {
+                               return false;
+                       }
+               }
+
+               public IDocRevisionManager RevisionManager {
+                       get {
+                               return null;
+                       }
+               }
+
+               public bool SupportChange {
+                       get {
+                               return false;
+                       }
+               }
+
+               public string Store (string id, string text)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               public string Store (string id, byte[] data)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               public string Store (string id, Stream stream)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               public Stream Retrieve (string id)
+               {
+                       var path = id;
+                       if ('/' != Path.DirectorySeparatorChar)
+                               path = path.Replace ('/', Path.DirectorySeparatorChar);
+                       return File.OpenRead (Path.Combine (basePath, path));
+               }
+
+               public IEnumerable<string> GetAvailableIds ()
+               {
+                       return Directory.EnumerateFiles (basePath, "*.xml", SearchOption.AllDirectories);
+               }
+
+               public void Dispose ()
+               {
+               }
+       }
+}
diff --git a/mcs/tools/monkeydoc/MonkeyDoc/storage/ZipStorage.cs b/mcs/tools/monkeydoc/MonkeyDoc/storage/ZipStorage.cs
new file mode 100644 (file)
index 0000000..81ed1c5
--- /dev/null
@@ -0,0 +1,131 @@
+using System;
+using System.IO;
+using System.Xml;
+using System.Linq;
+using System.Text;
+using System.Collections.Generic;
+
+using ICSharpCode.SharpZipLib.Zip;
+
+namespace MonkeyDoc.Storage
+{
+       public class ZipStorage : IDocStorage
+       {
+               string zipFileName;
+               int code;
+               ZipOutputStream zipOutput;
+               ZipFile zipFile;
+               // SharpZipLib use linear search to map name to index, correct that a bit
+               Dictionary<string, int> entries = new Dictionary<string, int> ();
+
+               public ZipStorage (string zipFileName)
+               {
+                       this.zipFileName = zipFileName;
+               }
+
+               public bool SupportRevision {
+                       get {
+                               return false;
+                       }
+               }
+
+               public IDocRevisionManager RevisionManager {
+                       get {
+                               return null;
+                       }
+               }
+
+               public bool SupportChange {
+                       get {
+                               return true;
+                       }
+               }
+
+               public string Store (string id, string text)
+               {
+                       EnsureOutput ();
+                       SetupEntry (zipOutput, ref id);
+                       var writer = new StreamWriter (zipOutput);
+                       writer.Write (text);
+                       writer.Flush ();
+                       
+                       return id;
+               }
+
+               public string Store (string id, byte[] data)
+               {
+                       EnsureOutput ();
+                       SetupEntry (zipOutput, ref id);
+                       zipOutput.Write (data, 0, data.Length);
+                       return id;
+               }
+
+               public string Store (string id, Stream stream)
+               {
+                       EnsureOutput ();
+                       SetupEntry (zipOutput, ref id);
+                       stream.CopyTo (zipOutput);
+                       return id;
+               }
+
+               void SetupEntry (ZipOutputStream zipOutput, ref string id)
+               {
+                       if (string.IsNullOrEmpty (id))
+                               id = GetNewCode ();
+
+                       ZipEntry entry = new ZipEntry (id);
+                       zipOutput.PutNextEntry (entry);
+               }
+
+               public Stream Retrieve (string id)
+               {
+                       EnsureInput ();
+                       int index;
+                       ZipEntry entry;
+                       if (!entries.TryGetValue (id, out index) || (entry = zipFile[index]) == null)
+                               entry = zipFile.GetEntry (id);
+                       if (entry != null)
+                               return zipFile.GetInputStream (entry);
+                       else
+                               throw new ArgumentException ("id", string.Format ("'{0}' isn't a valid id for this storage", id));
+               }
+
+               public IEnumerable<string> GetAvailableIds ()
+               {
+                       EnsureInput ();
+                       return zipFile.Cast<ZipEntry> ().Select (ze => ze.Name);
+               }
+
+               void EnsureOutput ()
+               {
+                       if (zipFile != null)
+                               throw new InvalidOperationException ("This ZipStorage instance is already used in read-mode");
+                       if (zipOutput != null)
+                               return;
+                       zipOutput = new ZipOutputStream (File.Create (zipFileName));
+               }
+
+               void EnsureInput ()
+               {
+                       if (zipOutput != null)
+                               throw new InvalidOperationException ("This ZipStorage instance is already used in write-mode");
+                       if (zipFile != null)
+                               return;
+                       zipFile = new ZipFile (zipFileName);
+                       entries = Enumerable.Range (0, zipFile.Size).ToDictionary (i => zipFile[i].Name, i => i);
+               }
+
+               public void Dispose ()
+               {
+                       if (zipOutput != null)
+                               zipOutput.Dispose ();
+                       if (zipFile != null)
+                               zipFile.Close ();
+               }
+
+               string GetNewCode ()
+               {
+                       return String.Format ("{0}", code++);
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/Monkeydoc.Ecma/EcmaDesc.cs b/mcs/tools/monkeydoc/Monkeydoc.Ecma/EcmaDesc.cs
deleted file mode 100644 (file)
index 19c3ce4..0000000
+++ /dev/null
@@ -1,333 +0,0 @@
-using System;
-using System.Linq;
-using System.Text;
-using System.Collections.Generic;
-
-namespace MonkeyDoc.Ecma
-{
-       /* Some properties might not be filled/meaningful depending on kind
-        * like a namespace EcmaUrl won't have a valid TypeName
-        */
-       public class EcmaDesc : IEquatable<EcmaDesc>
-       {
-               public enum Kind
-               {
-                       Type,
-                       Constructor,
-                       Method,
-                       Namespace,
-                       Field,
-                       Property,
-                       Event,
-                       Operator
-               }
-
-               public enum Mod
-               {
-                       Normal,
-                       Pointer,
-                       Ref,
-                       Out
-               }
-
-               public enum Format
-               {
-                       WithArgs,
-                       WithoutArgs
-               }
-
-               public Kind DescKind {
-                       get;
-                       set;
-               }
-
-               public Mod DescModifier {
-                       get;
-                       set;
-               }
-
-               public string Namespace {
-                       get;
-                       set;
-               }
-
-               public string TypeName {
-                       get;
-                       set;
-               }
-
-               public string MemberName {
-                       get;
-                       set;
-               }
-
-               public EcmaDesc NestedType {
-                       get;
-                       set;
-               }
-
-               /* A list of the array dimensions attached to this type.
-                * The list count corresponds to the number of recursive
-                * array definition (jagged arrays) the value of the
-                * corresponding list item is the number of dimension
-                * attached to that array definition instance
-                */
-               public IList<int> ArrayDimensions {
-                       get;
-                       set;
-               }
-
-               /* Depending on the form of the url, we might not have the type
-                * of the argument but only how many the type/member has i.e.
-                * when such number is specified with a backtick
-                */
-               public IList<EcmaDesc> GenericTypeArguments {
-                       get;
-                       set;
-               }
-
-               public IList<EcmaDesc> GenericMemberArguments {
-                       get;
-                       set;
-               }
-
-               public IList<EcmaDesc> MemberArguments {
-                       get;
-                       set;
-               }
-
-               /* This indicates that we actually want an inner part of the ecmadesc
-                * i.e. in case of T: we could want the members (*), ctor (C), methods (M), ...
-                */
-               public char Etc {
-                       get;
-                       set;
-               }
-
-               public bool IsEtc {
-                       get {
-                               return Etc != (char)0;
-                       }
-               }
-
-               /* EtcFilter is only valid in some case of IsEtc when the inner part needs
-                * to be further filtered e.g. in case we want a listing of the type overloads
-                * Equals
-                */
-               public string EtcFilter {
-                       get;
-                       set;
-               }
-
-               /* When a member is an explicit implementation of an interface member, we register
-                * the member EcmaDesc with its interface parent here
-                */
-               public EcmaDesc ExplicitImplMember {
-                       get;
-                       set;
-               }
-
-               // Returns the TypeName and the generic/inner type information if existing
-               public string ToCompleteTypeName (char innerTypeSeparator = '.')
-               {
-                       var result = TypeName;
-                       if (GenericTypeArguments != null)
-                               result += FormatGenericArgs (GenericTypeArguments);
-                       if (NestedType != null)
-                               result += innerTypeSeparator + NestedType.ToCompleteTypeName ();
-                       if (ArrayDimensions != null && ArrayDimensions.Count > 0)
-                               result += ArrayDimensions.Select (dim => "[" + new string (',', dim - 1) + "]").Aggregate (string.Concat);
-
-                       return result;
-               }
-
-               // Returns the member name with its generic types if existing
-               public string ToCompleteMemberName (Format format)
-               {
-                       /* We special process two cases:
-                        *   - Explicit member implementation which append a full type specification
-                        *   - Conversion operator which are exposed as normal method but have specific captioning in the end
-                        */
-                       if (ExplicitImplMember != null) {
-                               var impl = ExplicitImplMember;
-                               return impl.FormattedNamespace + impl.ToCompleteTypeName () + "." + impl.ToCompleteMemberName (format);
-                       } else if (format == Format.WithArgs && DescKind == Kind.Operator && MemberName.EndsWith ("Conversion")) {
-                               var type1 = MemberArguments[0].FormattedNamespace + MemberArguments[0].ToCompleteTypeName () + ModToString (MemberArguments[0]);
-                               var type2 = MemberArguments[1].FormattedNamespace + MemberArguments[1].ToCompleteTypeName () + ModToString (MemberArguments[1]);
-                               return type1 + " to " + type2;
-                       }
-
-                       var result = IsEtc && !string.IsNullOrEmpty (EtcFilter) ? EtcFilter : MemberName;
-
-                       // Temporary hack for monodoc produced inner type ctor
-                       //if (DescKind == Kind.Constructor && NestedType != null)
-                               //result = ToCompleteTypeName ();
-
-                       if (GenericMemberArguments != null)
-                               result += FormatGenericArgs (GenericMemberArguments);
-
-                       if (format == Format.WithArgs) {
-                               result += '(';
-                               if (MemberArguments != null && MemberArguments.Count > 0) {
-                                       var args = MemberArguments.Select (a => FormatNamespace (a) + a.ToCompleteTypeName ('+') + ModToString (a));
-                                       result += string.Join (",", args);
-                               }
-                               result += ')';
-                       }
-
-                       return result;
-               }
-
-               public string ToEcmaCref ()
-               {
-                       var sb = new StringBuilder ();
-                       // Cref type
-                       sb.Append (DescKind.ToString ()[0]);
-                       // Create the rest
-                       ConstructCRef (sb);
-
-                       return sb.ToString ();
-               }
-
-               void ConstructCRef (StringBuilder sb)
-               {
-                       sb.Append (Namespace);
-                       if (DescKind == Kind.Namespace)
-                               return;
-
-                       sb.Append ('.');
-                       sb.Append (TypeName);
-                       if (GenericTypeArguments != null) {
-                               sb.Append ('<');
-                               foreach (var t in GenericTypeArguments)
-                                       t.ConstructCRef (sb);
-                               sb.Append ('>');
-                       }
-                       if (NestedType != null) {
-                               sb.Append ('+');
-                               NestedType.ConstructCRef (sb);
-                       }
-                       if (ArrayDimensions != null && ArrayDimensions.Count > 0) {
-                               for (int i = 0; i < ArrayDimensions.Count; i++) {
-                                       sb.Append ('[');
-                                       sb.Append (new string (',', ArrayDimensions[i] - 1));
-                                       sb.Append (']');
-                               }
-                       }
-                       if (DescKind == Kind.Type)
-                               return;
-
-                       if (MemberArguments != null) {
-                               
-                       }
-               }
-
-               public override string ToString ()
-               {
-                       return string.Format ("({8}) {0}::{1}{2}{3}{7} {4}{5}{6} {9} {10}",
-                                             Namespace,
-                                             TypeName,
-                                             FormatGenericArgsFull (GenericTypeArguments),
-                                             NestedType != null ? "+" + NestedType.ToString () : string.Empty,
-                                             MemberName ?? string.Empty,
-                                             FormatGenericArgsFull (GenericMemberArguments),
-                                             MemberArguments != null ? "(" + string.Join (",", MemberArguments.Select (m => m.ToString ())) + ")" : string.Empty,
-                                             ArrayDimensions != null && ArrayDimensions.Count > 0 ? ArrayDimensions.Select (dim => "[" + new string (',', dim - 1) + "]").Aggregate (string.Concat) : string.Empty,
-                                             DescKind.ToString ()[0],
-                                             Etc != 0 ? '(' + Etc.ToString () + ')' : string.Empty,
-                                             ExplicitImplMember != null ? "$" + ExplicitImplMember.ToString () : string.Empty);
-                                             
-               }
-
-               public override bool Equals (object other)
-               {
-                       var otherDesc = other as EcmaDesc;
-                       return otherDesc != null && Equals (otherDesc);
-               }
-
-               public bool Equals (EcmaDesc other)
-               {
-                       if (other == null)
-                               return false;
-
-                       if (NestedType == null ^ other.NestedType == null
-                           || ArrayDimensions == null ^ other.ArrayDimensions == null
-                           || GenericTypeArguments == null ^ other.GenericTypeArguments == null
-                           || GenericMemberArguments == null ^ other.GenericMemberArguments == null
-                           || MemberArguments == null ^ other.MemberArguments == null
-                           || ExplicitImplMember == null ^ other.ExplicitImplMember == null)
-                               return false;
-
-                       return other != null
-                               && DescKind == other.DescKind
-                               && TypeName == other.TypeName
-                               && Namespace == other.Namespace
-                               && MemberName == other.MemberName
-                               && (NestedType == null || NestedType.Equals (other.NestedType))
-                               && (ArrayDimensions == null || ArrayDimensions.SequenceEqual (other.ArrayDimensions))
-                               && (GenericTypeArguments == null || GenericTypeArguments.SequenceEqual (other.GenericTypeArguments))
-                               && (GenericMemberArguments == null || GenericMemberArguments.SequenceEqual (other.GenericMemberArguments))
-                               && (MemberArguments == null || MemberArguments.SequenceEqual (other.MemberArguments))
-                               && Etc == other.Etc
-                               && EtcFilter == other.EtcFilter
-                               && (ExplicitImplMember == null || ExplicitImplMember.Equals (other.ExplicitImplMember));
-               }
-
-               public override int GetHashCode ()
-               {
-                       return DescKind.GetHashCode ()
-                               ^ TypeName.GetHashCode ()
-                               ^ Namespace.GetHashCode ()
-                               ^ MemberName.GetHashCode ();
-               }
-
-               bool What (bool input)
-               {
-                       if (!input)
-                               throw new Exception ("Not equal");
-                       return input;
-               }
-
-               bool WhatT (bool input)
-               {
-                       if (input)
-                               throw new Exception ("Not equal");
-                       return input;
-               }
-
-               string FormatNamespace (EcmaDesc desc)
-               {
-                       return string.IsNullOrEmpty (desc.Namespace) ? string.Empty : desc.Namespace + ".";
-               }
-
-               string FormatGenericArgs (IEnumerable<EcmaDesc> genericArgs)
-               {
-                       return genericArgs != null ? "<" + string.Join (",", genericArgs.Select (t => FormatNamespace (t) + t.ToCompleteTypeName ())) + ">" : string.Empty;
-               }
-
-               string FormatGenericArgsFull (IEnumerable<EcmaDesc> genericArgs)
-               {
-                       return genericArgs != null ? "<" + string.Join (",", genericArgs.Select (t => t.ToString ())) + ">" : string.Empty;
-               }
-
-               string ModToString (EcmaDesc desc)
-               {
-                       switch (desc.DescModifier) {
-                       case Mod.Pointer:
-                               return "*";
-                       case Mod.Ref:
-                               return "&";
-                       case Mod.Out:
-                               return "@";
-                       default:
-                               return string.Empty;
-                       }
-               }
-
-               string FormattedNamespace {
-                       get {
-                               return !string.IsNullOrEmpty (Namespace) ? Namespace + "." : string.Empty;
-                       }
-               }
-       }
-}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/Monkeydoc.Ecma/EcmaUrlParser.jay b/mcs/tools/monkeydoc/Monkeydoc.Ecma/EcmaUrlParser.jay
deleted file mode 100644 (file)
index e136bc2..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-%{
-using System.Text;
-using System.IO;
-using System;
-using System.Linq;
-using System.Collections.Generic;
-
-namespace MonkeyDoc.Ecma
-{
-       public class EcmaUrlParser
-       {
-        int yacc_verbose_flag = 0;
-
-        public void IsValid (string input)
-        {
-                       var lexer = new EcmaUrlTokenizer (input);
-                       this.yyparse (lexer);
-        }
-
-        public EcmaDesc Parse (string input)
-        {
-                       var lexer = new EcmaUrlTokenizer (input);
-                       return (EcmaDesc)this.yyparse (lexer);
-        }
-
-        public bool TryParse (string input, out EcmaDesc desc)
-        {
-            desc = null;
-            try {
-                desc = Parse (input);
-            } catch {
-                return false;
-            }
-            return true;
-        }
-
-        EcmaDesc SetEcmaDescType (object result, EcmaDesc.Kind kind)
-        {
-            var desc = result as EcmaDesc;
-            desc.DescKind = kind;
-            return desc;
-        }
-
-        List<T> SafeReverse<T> (List<T> input)
-        {
-            if (input == null)
-               return null;
-            input.Reverse ();
-            return input;
-        }
-%}
-
-%token ERROR
-%token IDENTIFIER
-%token DIGIT
-%token DOT
-%token COMMA
-%token COLON
-%token INNER_TYPE_SEPARATOR
-%token OP_GENERICS_LT
-%token OP_GENERICS_GT
-%token OP_GENERICS_BACKTICK
-%token OP_OPEN_PAREN
-%token OP_CLOSE_PAREN
-%token OP_ARRAY_OPEN
-%token OP_ARRAY_CLOSE
-%token SLASH_SEPARATOR
-%token STAR
-%token REF_ARG
-%token OUT_ARG
-%token EXPLICIT_IMPL_SEP
-
-%start expression
-
-%%
-
-expression
-        : 'T' COLON type_expression { $$ = SetEcmaDescType ($3, EcmaDesc.Kind.Type); }
-        | 'N' COLON namespace_expression { $$ = SetEcmaDescType ($3, EcmaDesc.Kind.Namespace); }
-        | 'M' COLON method_expression { $$ = SetEcmaDescType ($3, EcmaDesc.Kind.Method); }
-        | 'F' COLON simple_member_expression { $$ = SetEcmaDescType ($3, EcmaDesc.Kind.Field); }
-        | 'C' COLON constructor_expression { $$ = SetEcmaDescType ($3, EcmaDesc.Kind.Constructor); }
-        | 'P' COLON property_expression { $$ = SetEcmaDescType ($3, EcmaDesc.Kind.Property); }
-        | 'E' COLON simple_member_expression { $$ = SetEcmaDescType ($3, EcmaDesc.Kind.Event); }
-        | 'O' COLON operator_expression { $$ = SetEcmaDescType ($3, EcmaDesc.Kind.Operator); }
-
-/* i.e. id.id.id or id */
-dot_expression
-        : IDENTIFIER { $$ = new List<string> { (string)$1 }; }
-        | IDENTIFIER DOT dot_expression { ((ICollection<string>)$3).Add ((string)$1); $$ = $3; }
-
-namespace_expression
-        : dot_expression { $$ = new EcmaDesc { Namespace = string.Join (".", ((IEnumerable<string>)$1).Reverse ()) }; }
-
-type_expression
-        : dot_expression type_expression_suffix {
-                         var dotExpr = ((List<string>)$1);
-                         dotExpr.Reverse ();
-                         var desc = $2 as EcmaDesc;
-                         desc.DescKind = EcmaDesc.Kind.Type;
-                         desc.Namespace = string.Join (".", dotExpr.Take (dotExpr.Count - 1));
-                         desc.TypeName = dotExpr.Last ();
-                         $$ = desc;
-                     }
-
-/* To be used in types with no namespaces attached to them like an inner type*/
-reduced_type_expression
-        : IDENTIFIER type_expression_suffix {
-                         var desc = $2 as EcmaDesc;
-                         desc.DescKind = EcmaDesc.Kind.Type;
-                         desc.TypeName = $1 as string;
-                         $$ = desc;
-                     }
-
-type_expression_suffix
-        : opt_generic_type_suffix opt_inner_type_description opt_array_definition opt_etc {
-                         bool nestedDescHasEtc = $2 != null && ((EcmaDesc)$2).IsEtc;
-                         EcmaDesc nestedType = (EcmaDesc)$2;
-                         $$ = new EcmaDesc {
-                            GenericTypeArguments = $1 as List<EcmaDesc>,
-                            NestedType = nestedType,
-                            ArrayDimensions = SafeReverse ($3 as List<int>),
-                            Etc = $4 != null ? ((Tuple<char, string>)$4).Item1 : nestedDescHasEtc ? nestedType.Etc : (char)0,
-                            EtcFilter = $4 != null ? ((Tuple<char, string>)$4).Item2 : nestedDescHasEtc ? nestedType.EtcFilter : null
-                         };
-                         if (nestedDescHasEtc) {
-                            nestedType.Etc = (char)0;
-                            nestedType.EtcFilter = null;
-                         }
-                     }
-
-opt_inner_type_description
-        : /* empty */ { $$ = null; }
-        | INNER_TYPE_SEPARATOR reduced_type_expression { $$ = $2; }
-
-opt_generic_type_suffix
-        : /* empty */ { $$ = null; }
-        | OP_GENERICS_BACKTICK DIGIT { $$ = Enumerable.Repeat<string> (null, (int)$2).ToList (); }
-        | OP_GENERICS_LT generic_type_arg_list OP_GENERICS_GT { $$ = $2; }
-
-generic_type_arg_list
-        : type_expression { $$ = new List<EcmaDesc> () { (EcmaDesc)$1 }; }
-        | generic_type_arg_list COMMA type_expression { ((List<EcmaDesc>)$1).Add ((EcmaDesc)$3); $$ = $1; }
-
-opt_array_definition
-        : /* empty */ { $$ = null; }
-        | OP_ARRAY_OPEN opt_array_definition_list OP_ARRAY_CLOSE opt_array_definition {
-                      var dims = ((IList<int>)$4) ?? new List<int> (2);
-                      dims.Add ((int)$2);
-                      $$ = dims;
-                }
-
-opt_array_definition_list
-        : /* empty */ { $$ = 1; }
-        | COMMA opt_array_definition_list { $$ = ((int)$2) + 1; }
-
-opt_etc
-        : /* empty */ { $$ = null; }
-        | SLASH_SEPARATOR etc_identifier { $$ = Tuple.Create<char, string> (((string)$2)[0], null); }
-        | SLASH_SEPARATOR etc_identifier SLASH_SEPARATOR reduced_member_expression { $$ = Tuple.Create<char, string> (((string)$2)[0], (string)$4); }
-/*        | SLASH_SEPARATOR etc_identifier SLASH_SEPARATOR IDENTIFIER opt_generic_type_suffix { $$ = Tuple.Create<char, string> (((string)$2)[0], (string)$4 + ($5 == null ? string.Empty : "<" + string.Join (",", ((IEnumerable<EcmaDesc>)$5).Select (t => t.ToCompleteTypeName ())) + ">")); } */
-
-etc_identifier
-        : STAR { $$ = "*"; }
-        | IDENTIFIER { $$ = $1; }
-
-method_expression
-        : type_expression DOT IDENTIFIER opt_generic_type_suffix opt_arg_list_suffix {
-                      var desc = $1 as EcmaDesc;
-                      desc.MemberName = $3 as string;
-                      desc.GenericMemberArguments = $4 as List<EcmaDesc>;
-                      desc.MemberArguments = SafeReverse ($5 as List<EcmaDesc>);
-                      $$ = desc;
-                }
-        | dot_expression opt_generic_type_suffix opt_arg_list_suffix {
-                      var dotExpr = ((List<string>)$1);
-                      $$ = new EcmaDesc {
-                           Namespace = string.Join (".", dotExpr.Skip (2).DefaultIfEmpty (string.Empty).Reverse ()),
-                           TypeName = dotExpr.Skip (1).First (),
-                           MemberName = dotExpr.First (),
-                           GenericMemberArguments = $2 as List<EcmaDesc>,
-                           MemberArguments = SafeReverse ($3 as List<EcmaDesc>)
-                      };
-                }
-        | type_expression EXPLICIT_IMPL_SEP method_expression {
-                      var desc = $1 as EcmaDesc;
-                      desc.ExplicitImplMember = $3 as EcmaDesc;
-                      $$ = desc;
-                }
-
-/* To be used with members that may have no type/namespace attached */
-reduced_member_expression
-        : IDENTIFIER opt_generic_type_suffix { $$ = (string)$1 + ($2 == null ? string.Empty : "<" + string.Join (",", ((IEnumerable<EcmaDesc>)$2).Select (t => t.ToCompleteTypeName ())) + ">"); }
-        | IDENTIFIER opt_generic_type_suffix DOT reduced_member_expression {
-                      var existing = $4 as string;
-                      var expr = (string)$1 + ($2 == null ? string.Empty : "<" + string.Join (",", ((IEnumerable<EcmaDesc>)$2).Select (t => t.ToCompleteTypeName ())) + ">");
-                      $$ = expr + "." + existing;
-                }
-
-arg_type_expression
-        : type_expression opt_arg_type_suffix { var desc = (EcmaDesc)$1; desc.DescModifier = (EcmaDesc.Mod)$2; $$ = desc; }
-
-opt_arg_type_suffix
-        : /* empty */ { $$ = EcmaDesc.Mod.Normal; }
-        | STAR { $$ = EcmaDesc.Mod.Pointer; }
-        | REF_ARG { $$ = EcmaDesc.Mod.Ref; }
-        | OUT_ARG { $$ = EcmaDesc.Mod.Out; }
-
-type_expression_list
-        : /* empty */ { $$ = null; }
-        | arg_type_expression { $$ = new List<EcmaDesc> () { (EcmaDesc)$1 }; }
-        | arg_type_expression COMMA type_expression_list { ((List<EcmaDesc>)$3).Add ((EcmaDesc)$1); $$ = $3; }
-
-simple_member_expression
-        : dot_expression {
-                 var dotExpr = ((List<string>)$1);
-                 dotExpr.Reverse ();
-
-                 $$ = new EcmaDesc {
-                      Namespace = dotExpr.Count > 2 ? string.Join (".", dotExpr.Take (dotExpr.Count - 2)) : string.Empty,
-                      TypeName = dotExpr.Count > 1 ?  dotExpr[dotExpr.Count - 2] : string.Empty,
-                      MemberName = dotExpr[dotExpr.Count - 1]
-                 };
-             }
-        | type_expression DOT IDENTIFIER {
-                 var desc = $1 as EcmaDesc;
-                 desc.MemberName = $3 as string;
-                 $$ = desc;
-             }
-        | type_expression EXPLICIT_IMPL_SEP simple_member_expression {
-                 var desc = $1 as EcmaDesc;
-                 desc.ExplicitImplMember = $3 as EcmaDesc;
-                 $$ = desc;
-             }
-
-constructor_expression
-        : method_expression { $$ = $1; }
-
-operator_expression
-        : method_expression { $$ = $1; }
-
-property_expression
-        : simple_member_expression opt_property_indexer {
-                 var desc = $1 as EcmaDesc;
-                 (desc.ExplicitImplMember ?? desc).MemberArguments = SafeReverse ($2 as List<EcmaDesc>);
-                 $$ = desc;
-             }
-
-opt_property_indexer
-        : opt_arg_list_suffix { $$ = $1; }
-
-/*simple_member_expression opt_arg_list_suffix { $$ = CopyFromEcmaDesc (new EcmaDesc {
-                           MemberArguments = SafeReverse ($2 as List<EcmaDesc>)
-                      }, (EcmaDesc)$1);
-                }*/
-
-opt_arg_list_suffix
-        : /* empty */ { $$ = null; }
-        | OP_OPEN_PAREN type_expression_list OP_CLOSE_PAREN { $$ = $2; }
-
-%%
-
-}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/Monkeydoc.Ecma/EcmaUrlParserDriver.cs b/mcs/tools/monkeydoc/Monkeydoc.Ecma/EcmaUrlParserDriver.cs
deleted file mode 100644 (file)
index af3978f..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-using System.IO;
-
-namespace MonkeyDoc.Ecma
-{
-       public class EcmaUrlParserDriver
-       {
-               public static void Main (string[] args)
-               {
-                       var input = new StringReader (args[0]);
-                       var lexer = new EcmaUrlTokenizer (input);
-                       var parser = new EcmaUrlParser ();
-
-                       Console.WriteLine (parser.yyparse (lexer));
-               }
-       }
-}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/Monkeydoc.Ecma/EcmaUrlTokenizer.cs b/mcs/tools/monkeydoc/Monkeydoc.Ecma/EcmaUrlTokenizer.cs
deleted file mode 100644 (file)
index 91bf6db..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-using System;
-using System.Text;
-using System.Globalization;
-
-namespace MonkeyDoc.Ecma
-{
-       public class EcmaUrlTokenizer : yyParser.yyInput
-       {
-               const char EndOfStream = (char)0;
-               string input;
-               object val;
-               int current_token;
-               int current_pos;
-               int real_current_pos;
-               int identCount = 0;
-
-               public EcmaUrlTokenizer (string input)
-               {
-                       this.input = input;
-               }
-
-               static bool is_identifier_start_character (char c)
-               {
-                       return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || Char.IsLetter (c);
-               }
-
-               static bool is_identifier_part_character (char c)
-               {
-                       if (c >= 'a' && c <= 'z')
-                               return true;
-
-                       if (c >= 'A' && c <= 'Z')
-                               return true;
-
-                       if (c == '_' || (c >= '0' && c <= '9'))
-                               return true;
-
-                       if (c < 0x80)
-                               return false;
-
-                       return Char.IsLetter (c) || Char.GetUnicodeCategory (c) == UnicodeCategory.ConnectorPunctuation;
-               }
-
-               public bool advance ()
-               {
-                       return Peek () != EndOfStream;
-               }
-
-               public Object Value {
-                       get {
-                               return val;
-                       }
-               }
-
-               public Object value ()
-               {
-                       return val;
-               }
-
-               public int token ()
-               {
-                       int token = xtoken ();
-                       //Console.WriteLine ("Current token {0} with value {1}", token, val == null ? "(none)" : val.ToString ());
-                       if (token == Token.ERROR)
-                               Console.WriteLine ("Problem at pos {0} after token {1}", current_pos, current_token);
-                       current_token = token;
-                       return token;
-               }
-
-               int xtoken ()
-               {
-                       char next = Read ();
-                       while (char.IsWhiteSpace (next))
-                               next = Read ();
-                       current_pos++;
-                       val = null;
-
-                       switch (next) {
-                       case ',':
-                               return Token.COMMA;
-                       case '.':
-                               return Token.DOT;
-                       case '<':
-                               return Token.OP_GENERICS_LT;
-                       case '>':
-                               return Token.OP_GENERICS_GT;
-                       case '`':
-                               return Token.OP_GENERICS_BACKTICK;
-                       case '(':
-                               return Token.OP_OPEN_PAREN;
-                       case ')':
-                               return Token.OP_CLOSE_PAREN;
-                       case '+':
-                               return Token.INNER_TYPE_SEPARATOR;
-                       case ':':
-                               return Token.COLON;
-                       case '/':
-                               return Token.SLASH_SEPARATOR;
-                       case '[':
-                               return Token.OP_ARRAY_OPEN;
-                       case ']':
-                               return Token.OP_ARRAY_CLOSE;
-                       case '*':
-                               return Token.STAR;
-                       case '&':
-                               return Token.REF_ARG;
-                       case '@':
-                               return Token.OUT_ARG;
-                       case '$':
-                               return Token.EXPLICIT_IMPL_SEP;
-                       default:
-                               return TokenizeIdentifierOrNumber (next);
-                       }
-               }
-
-               int TokenizeIdentifierOrNumber (char current)
-               {
-                       // We must first return the expression type which is a uppercase letter and a colon
-                       if (current_pos < 2) {
-                               val = null;
-                               return (int)current;
-                       }
-
-                       if (is_identifier_start_character (current) || current == '*') {
-                               unsafe {
-                                       // identifier length is artificially limited to 1024 bytes by implementations
-                                       char* pIdent = stackalloc char[512];
-                                       *pIdent = current;
-                                       identCount = 1;
-
-                                       char peek;
-                                       while ((peek = Peek ()) != EndOfStream && is_identifier_part_character (peek)) {
-                                               *(pIdent + identCount) = Read ();
-                                               ++current_pos;
-                                               ++identCount;
-                                       }
-
-                                       val = new string ((char*)pIdent, 0, identCount);
-                                       return Token.IDENTIFIER;
-                               }
-                       } else if (char.IsDigit (current)) {
-                               val = current - '0';
-                               return Token.DIGIT;
-                       } else {
-                               val = null;
-                               return Token.ERROR;
-                       }
-               }
-
-               char Read ()
-               {
-                       try {
-                               return input[real_current_pos++];
-                       } catch {
-                               return EndOfStream;
-                       }
-               }
-
-               char Peek ()
-               {
-                       try {
-                               return input[real_current_pos];
-                       } catch {
-                               return EndOfStream;
-                       }
-               }
-       }
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/HelpSource.cs b/mcs/tools/monkeydoc/Monkeydoc/HelpSource.cs
deleted file mode 100644 (file)
index 14cf446..0000000
+++ /dev/null
@@ -1,339 +0,0 @@
-using System;
-using System.IO;
-using System.Linq;
-using System.Xml;
-using System.Diagnostics;
-using System.Collections.Generic;
-
-using Mono.Utilities;
-using Lucene.Net.Index;
-
-namespace MonkeyDoc
-{
-       //
-       // The HelpSource class keeps track of the archived data, and its
-       // tree
-       //
-       public class HelpSource
-       {
-               static int id;
-
-               //
-               // The unique ID for this HelpSource.
-               //
-               int source_id;
-
-               // The name of the HelpSource, used by all the file (.tree, .zip, ...) used by it
-               string name;
-               // The full directory path where the HelpSource files are located
-               string basePath;
-
-               // The tree of this help source
-               Tree tree;
-               string treeFilePath;
-               RootTree rootTree;
-
-               IDocCache cache;
-               IDocStorage storage;
-
-               public HelpSource (string base_filename, bool create)
-               {
-                       this.name = Path.GetFileName (base_filename);
-                       this.basePath = Path.GetDirectoryName (base_filename);
-                       this.treeFilePath = base_filename + ".tree";
-                       this.storage = new MonkeyDoc.Storage.ZipStorage (base_filename + ".zip");
-                       this.cache = DocCacheHelper.GetDefaultCache (Name);
-
-                       tree = create ? new Tree (this, string.Empty, string.Empty) : new Tree (this, treeFilePath);
-
-                       source_id = id++;
-               }
-       
-               public HelpSource ()
-               {
-                       tree = new Tree (this, "Blah", "Blah");
-                       source_id = id++;
-               }
-       
-               public int SourceID {
-                       get {
-                               return source_id;
-                       }
-               }
-       
-               public string Name {
-                       get {
-                               return name;
-                       }
-               }
-
-               /* This gives the full path of the source/ directory */
-               public string BaseFilePath {
-                       get {
-                               return basePath;
-                       }
-               }
-
-               public TraceLevel TraceLevel {
-                       get;
-                       set;
-               }
-
-               public string BaseDir {
-                       get {
-                               return basePath;
-                       }
-               }
-
-               public Tree Tree {
-                       get {
-                               return tree;
-                       }
-               }
-
-               public RootTree RootTree {
-                       get {
-                               return rootTree;
-                       }
-                       set {
-                               rootTree = value;
-                       }
-               }
-
-               public IDocCache Cache {
-                       get {
-                               return cache;
-                       }
-               }
-
-               public IDocStorage Storage {
-                       get {
-                               return storage;
-                       }
-                       protected set {
-                               storage = value;
-                       }
-               }
-
-               // A HelpSource may have a common prefix to its URL, give it here
-               protected virtual string UriPrefix {
-                       get {
-                               return "dummy:";
-                       }
-               }
-       
-               /// <summary>
-               ///   Returns a stream from the packaged help source archive
-               /// </summary>
-               public virtual Stream GetHelpStream (string id)
-               {
-                       return storage.Retrieve (id);
-               }
-
-               public virtual Stream GetCachedHelpStream (string id)
-               {
-                       if (string.IsNullOrEmpty (id))
-                               throw new ArgumentNullException ("id");
-                       if (!cache.CanCache (DocEntity.Text))
-                               return GetHelpStream (id);
-                       if (!cache.IsCached (id))
-                               cache.CacheText (id, GetHelpStream (id));
-                       return cache.GetCachedStream (id);
-               }
-
-               public XmlReader GetHelpXml (string id)
-               {
-                       var url = "monodoc:///" + SourceID + "@" + Uri.EscapeDataString (id) + "@";
-                       var stream = cache.IsCached (id) ? cache.GetCachedStream (id) : storage.Retrieve (id);
-                       
-                       return stream == null ? null : new XmlTextReader (url, stream);
-               }
-       
-               public virtual XmlDocument GetHelpXmlWithChanges (string id)
-               {
-                       XmlDocument doc = new XmlDocument ();
-                       if (!storage.SupportRevision) {
-                               doc.Load (GetHelpXml (id));
-                       } else {
-                               var revManager = storage.RevisionManager;
-                               doc.Load (revManager.RetrieveLatestRevision (id));
-                       }
-                       return doc;
-               }
-
-               public virtual string GetCachedText (string id)
-               {
-                       if (!cache.CanCache (DocEntity.Text))
-                               return GetText (id);
-                       if (!cache.IsCached (id))
-                               cache.CacheText (id, GetText (id));
-                       return cache.GetCachedString (id);
-               }
-
-               public virtual string GetText (string id)
-               {
-                       return new StreamReader (GetHelpStream (id)).ReadToEnd ();
-               }
-
-               // Tells if the result for the provided id is generated dynamically
-               // by the help source
-               public virtual bool IsGeneratedContent (string id)
-               {
-                       return false;
-               }
-
-               // Tells if the content of the provided id is meant to be returned raw
-               public virtual bool IsRawContent (string id)
-               {
-                       return false;
-               }
-
-               // Tells if provided id refers to a multi-content-type document if it's case
-               // tells the ids it's formed of
-               public virtual bool IsMultiPart (string id, out IEnumerable<string> parts)
-               {
-                       parts = null;
-                       return false;
-               }
-
-               /// <summary>
-               ///   Saves the tree and the archive
-               /// </summary>
-               public void Save ()
-               {
-                       tree.Save (treeFilePath);
-                       storage.Dispose ();
-               }
-       
-               public virtual void RenderPreviewDocs (XmlNode newNode, XmlWriter writer)
-               {
-                       throw new NotImplementedException ();
-               }
-
-               public virtual string GetPublicUrl (Node node)
-               {
-                       return node.GetInternalUrl ();
-               }
-
-               public virtual bool CanHandleUrl (string url)
-               {
-                       return url.StartsWith (UriPrefix, StringComparison.OrdinalIgnoreCase);
-               }
-
-               public virtual string GetInternalIdForUrl (string url, out Node node)
-               {
-                       node = MatchNode (url);
-                       return node == null ? null : url.Substring (UriPrefix.Length);
-               }
-               
-               public virtual Node MatchNode (string url)
-               {
-                       Node current = null;
-
-                       var matchCache = LRUCache<string, Node>.Default;
-                       if ((current = matchCache.Get (url)) != null)
-                               return current;
-
-                       current = Tree.RootNode;
-                       var strippedUrl = url.StartsWith (UriPrefix, StringComparison.OrdinalIgnoreCase) ? url.Substring (UriPrefix.Length) : url;
-                       var searchNode = new Node () { Element = strippedUrl };
-
-                       do {
-                               int index = current.Nodes.BinarySearch (searchNode, NodeElementComparer.Instance);
-                               if (index >= 0) {
-                                       Node n = current.Nodes[index];
-                                       //Console.WriteLine ("Binarysearch success for {0} which fell on {1}", strippedUrl, n.Element);
-                                       matchCache.Put (url, n);
-                                       return n;
-                               }
-                               index = ~index;
-                               if (index == current.Nodes.Count) {
-                                       //Console.WriteLine ("Match fail for {0}", strippedUrl);
-                                       //Console.WriteLine (current.Nodes.Select (n => n.Element).Aggregate ((e1, e2) => e1 + ", " + e2));
-                                       return SlowMatchNode (Tree.RootNode, matchCache, strippedUrl);
-                               }
-                               current = current.Nodes [index - 1];
-                               //Console.WriteLine ("Binarysearch failed for {0}, next node check is {1}", strippedUrl, current.Element);
-                       } while (true);
-
-                       return null;
-               }
-
-               /* That slow path is mainly here to handle ecmaspec type of url which are composed of hard to sort numbers
-                * because they don't have the same amount of digit. We could use a regex to harmonise the various number
-                * parts but then it would be quite specific. Since in the case of ecmaspec the tree is well-formed enough
-                * the "Slow" match should still be fast enough
-                */
-               Node SlowMatchNode (Node current, LRUCache<string, Node> matchCache, string url)
-               {
-                       //Console.WriteLine ("Entering slow path for {0} starting from {1}", url, current.Element);
-                       while (current != null) {
-                               bool stop = true;
-                               foreach (Node n in current.Nodes) {
-                                       var element = n.Element.StartsWith (UriPrefix, StringComparison.OrdinalIgnoreCase) ? n.Element.Substring (UriPrefix.Length) : n.Element;
-                                       if (url == element) {
-                                               matchCache.Put (url, n);
-                                               return n;
-                                       } else if (url.StartsWith (element + ".", StringComparison.OrdinalIgnoreCase) && !n.IsLeaf) {
-                                               current = n;
-                                               stop = false;
-                                               break;
-                                       }
-                               }
-                               if (stop)
-                                       current = null;
-                       }
-
-                       return null;
-               }
-               
-               class NodeElementComparer : IComparer<Node>
-               {
-                       public static NodeElementComparer Instance = new NodeElementComparer ();
-
-                       public int Compare (Node n1, Node n2)
-                       {
-                               return string.Compare (Cleanup (n1), Cleanup (n2), StringComparison.Ordinal);
-                       }
-
-                       string Cleanup (Node n)
-                       {
-                               var prefix = n.Tree != null && n.Tree.HelpSource != null ? n.Tree.HelpSource.UriPrefix : string.Empty;
-                               var element = n.Element.StartsWith (prefix, StringComparison.OrdinalIgnoreCase) ? n.Element.Substring (prefix.Length) : n.Element;
-                               if (char.IsDigit (element, 0)) {
-                                       var count = element.TakeWhile (char.IsDigit).Count ();
-                                       element = element.PadLeft (Math.Max (0, 3 - count) + element.Length, '0');
-                               }
-                               //Console.WriteLine ("Cleaned up {0} to {1}", n.Element, element);
-                               return element;
-                       }
-               }
-
-               public virtual DocumentType GetDocumentTypeForId (string id, out Dictionary<string, string> extraParams)
-               {
-                       extraParams = null;
-                       return DocumentType.PlainText;
-               }
-
-               public virtual Stream GetImage (string url)
-               {
-                       return null;
-               }
-
-               //
-               // Populates the index.
-               //
-               public virtual void PopulateIndex (IndexMaker index_maker)
-               {
-               }
-
-               //
-               // Create different Documents for adding to Lucene search index
-               // The default action is do nothing. Subclasses should add the docs
-               // 
-               public virtual void PopulateSearchableIndex (IndexWriter writer)
-               {
-
-               }
-       }
-}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/Monkeydoc/Node.cs b/mcs/tools/monkeydoc/Monkeydoc/Node.cs
deleted file mode 100644 (file)
index 8d9bd1e..0000000
+++ /dev/null
@@ -1,323 +0,0 @@
-using System;
-using System.IO;
-using System.Text;
-using System.Linq;
-using System.Xml;
-using System.Collections.Generic;
-
-namespace MonkeyDoc
-{
-       public class Node : IComparable<Node>, IComparable
-       {
-               readonly Tree tree;
-               string caption, element, pubUrl;
-               public bool Documented;
-               bool loaded;
-               Node parent;
-               List<Node> nodes;
-               Dictionary<string, Node> childrenLookup;
-               /* Address has three types of value, 
-                *   _ 0 is for no on-disk representation
-                *   _ >0 is a valid address that is loaded immediately
-                *   _ <0 is a valid negated address to indicate lazy loading
-                */
-               int address;
-
-               public Node (Node parent, string caption, string element) : this (parent.Tree, caption, element)
-               {
-                       this.parent = parent;
-               }
-
-               internal Node (Tree tree, string caption, string element)
-               {
-                       this.tree = tree;
-                       this.caption = caption;
-                       this.element = element;
-               }
-       
-               /// <summary>
-               ///    Creates a node from an on-disk representation
-               /// </summary>
-               internal Node (Node parent, int address) : this (parent.tree, address)
-               {
-                       this.parent = parent;
-               }
-
-               internal Node (Tree tree, int address)
-               {
-                       this.address = address;
-                       this.tree = tree;
-                       if (address > 0)
-                               LoadNode ();
-               }
-
-               /* This is solely used for MatchNode to check for equality */
-               internal Node ()
-               {
-               }
-
-               void LoadNode ()
-               {
-                       tree.InflateNode (this);
-                       if (parent != null)
-                               parent.RegisterFullNode (this);
-               }
-
-               public void AddNode (Node n)
-               {
-                       nodes.Add (n);
-                       n.parent = this;
-                       n.Documented = true;
-                       RegisterFullNode (n);
-               }
-
-               public void DeleteNode (Node n)
-               {
-                       nodes.Remove (n);
-                       if (!string.IsNullOrEmpty (n.element))
-                               childrenLookup.Remove (n.element);
-               }
-
-               // When a child node is inflated, it calls this method
-               // so that we can add it to our lookup for quick search
-               void RegisterFullNode (Node child)
-               {
-                       if (childrenLookup == null)
-                               childrenLookup = new Dictionary<string, Node> ();
-                       if (!string.IsNullOrEmpty (child.element))
-                               childrenLookup[child.element] = child;
-               }
-
-               public List<Node> Nodes {
-                       get {
-                               EnsureLoaded ();
-                               return nodes != null ? nodes : new List<Node> ();
-                       }
-               }
-
-               public string Element {
-                       get {
-                               EnsureLoaded ();
-                               return element;
-                       }
-                       set {
-                               element = value;
-                       }
-               }
-
-               public string Caption {
-                       get {
-                               EnsureLoaded ();
-                               return caption;
-                       }
-                       internal set {
-                               caption = value;
-                       }
-               }
-       
-               public Node Parent {
-                       get {
-                               return parent;
-                       }
-               }
-
-               public Tree Tree {
-                       get {
-                               return tree;
-                       }
-               }
-
-               internal int Address {
-                       get {
-                               return address;
-                       }
-               }
-       
-               /// <summary>
-               ///   Creates a new node, in the locator entry point, and with
-               ///   a user visible caption of @caption
-               /// </summary>
-               public Node CreateNode (string c_caption, string c_element)
-               {
-                       EnsureNodes ();
-                       if (string.IsNullOrEmpty (c_caption))
-                               throw new ArgumentNullException ("c_caption");
-                       if (string.IsNullOrEmpty (c_element))
-                               throw new ArgumentNullException ("c_element");
-
-                       Node t = new Node (this, c_caption, c_element);
-                       nodes.Add (t);
-                       childrenLookup[c_element] = t;
-
-                       return t;
-               }
-
-               public Node GetOrCreateNode (string c_caption, string c_element)
-               {
-                       if (nodes == null)
-                               return CreateNode (c_caption, c_element);
-                       if (childrenLookup.Count != nodes.Count || (nodes.Count == 0 && childrenLookup.Count != nodes.Capacity))
-                               UpdateLookup ();
-
-                       Node result;
-                       if (!childrenLookup.TryGetValue (c_element, out result))
-                               result = CreateNode (c_caption, c_element);
-                       return result;
-               }
-
-               public void EnsureNodes ()
-               {
-                       if (nodes == null) {
-                               nodes = new List<Node> ();
-                               childrenLookup = new Dictionary<string, Node> ();
-                       }
-               }
-
-               public void EnsureLoaded ()
-               {
-                       if (address < 0 && !loaded) {
-                               LoadNode ();
-                               loaded = true;
-                       }
-               }
-
-               void UpdateLookup ()
-               {
-                       foreach (var node in nodes)
-                               childrenLookup[node.Element] = node;
-               }
-       
-               public bool IsLeaf {
-                       get {
-                               return nodes == null || nodes.Count == 0;
-                       }
-               }
-
-               void EncodeInt (BinaryWriter writer, int value)
-               {
-                       do {
-                               int high = (value >> 7) & 0x01ffffff;
-                               byte b = (byte)(value & 0x7f);
-
-                               if (high != 0) {
-                                       b = (byte)(b | 0x80);
-                               }
-                       
-                               writer.Write(b);
-                               value = high;
-                       } while(value != 0);
-               }
-
-               int DecodeInt (BinaryReader reader)
-               {
-                       int ret = 0;
-                       int shift = 0;
-                       byte b;
-               
-                       do {
-                               b = reader.ReadByte();
-
-                               ret = ret | ((b & 0x7f) << shift);
-                               shift += 7;
-                       } while ((b & 0x80) == 0x80);
-                       
-                       return ret;
-               }
-
-               internal void Deserialize (BinaryReader reader)
-               {
-                       int count = DecodeInt (reader);
-                       element = reader.ReadString ();
-                       caption = reader.ReadString ();
-
-                       if (count == 0)
-                               return;
-               
-                       nodes = new List<Node> (count);
-                       for (int i = 0; i < count; i++) {
-                               int child_address = DecodeInt (reader);
-                                                             
-                               Node t = new Node (this, -child_address);
-                               nodes.Add (t);
-                       }
-               }
-
-               internal void Serialize (FileStream output, BinaryWriter writer)
-               {
-                       if (nodes != null)
-                               foreach (Node child in nodes)
-                                       child.Serialize (output, writer);
-
-                       address = (int) output.Position;
-                       EncodeInt (writer, nodes == null ? 0 : (int) nodes.Count);
-                       writer.Write (element);
-                       writer.Write (caption);
-
-                       if (nodes != null)
-                               foreach (Node child in nodes)
-                                       EncodeInt (writer, child.address);
-               }
-
-               public void Sort ()
-               {
-                       if (nodes != null)
-                               nodes.Sort ();
-               }
-
-               internal string GetInternalUrl ()
-               {
-                       EnsureLoaded ();
-                       if (element.IndexOf (":") != -1 || parent == null)
-                               return element;
-
-                       var parentUrl = parent.GetInternalUrl ();
-                       return parentUrl.EndsWith ("/") ? parentUrl + element : parentUrl + "/" + element;
-               }
-               
-               public string PublicUrl {
-                       get {
-                               if (pubUrl != null)
-                                       return pubUrl;
-                               return pubUrl = tree.HelpSource != null ? tree.HelpSource.GetPublicUrl (this) : GetInternalUrl ();
-                       }
-               }
-
-               int IComparable.CompareTo (object obj)
-               {
-                       Node other = obj as Node;
-                       if (other == null)
-                               return -1;
-                       return CompareToInternal (other);
-               }
-
-               int IComparable<Node>.CompareTo (Node obj)
-               {
-                       return CompareToInternal (obj);
-               }
-
-               int CompareToInternal (Node other)
-               {
-                       EnsureLoaded ();
-                       other.EnsureLoaded ();
-
-                       var cap1 = caption;
-                       var cap2 = other.caption;
-
-                       /* Some node (notably from ecmaspec) have number prepended to them
-                        * which we need to sort better by padding them to the same number
-                        * of digits
-                        */
-                       if (char.IsDigit (cap1[0]) && char.IsDigit (cap2[0])) {
-                               int c1 = cap1.TakeWhile (char.IsDigit).Count ();
-                               int c2 = cap2.TakeWhile (char.IsDigit).Count ();
-                               
-                               if (c1 != c2) {
-                                       cap1 = cap1.PadLeft (cap1.Length + Math.Max (0, c2 - c1), '0');
-                                       cap2 = cap2.PadLeft (cap2.Length + Math.Max (0, c1 - c2), '0');
-                               }
-                       }
-
-                       return string.Compare (cap1, cap2, StringComparison.Ordinal);
-               }
-       }
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/Provider.cs b/mcs/tools/monkeydoc/Monkeydoc/Provider.cs
deleted file mode 100644 (file)
index 03c54e5..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-using System;
-
-namespace MonkeyDoc
-{
-       public abstract class Provider
-       {
-               //
-               // This code is used to "tag" all the different sources
-               //
-               static short serial;
-
-               public int Code { get; set; }
-
-               public Provider ()
-               {
-                       Code = serial++;
-               }
-
-               public abstract void PopulateTree (Tree tree);
-
-               //
-               // Called at shutdown time after the tree has been populated to perform
-               // any fixups or final tasks.
-               //
-               public abstract void CloseTree (HelpSource hs, Tree tree);
-       }
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/RootTree.cs b/mcs/tools/monkeydoc/Monkeydoc/RootTree.cs
deleted file mode 100644 (file)
index 9725655..0000000
+++ /dev/null
@@ -1,522 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.Configuration;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Runtime.InteropServices;
-using System.Xml;
-
-using MonkeyDoc.Providers;
-using Lucene.Net.Analysis.Standard;
-using Lucene.Net.Index;
-
-namespace MonkeyDoc
-{
-       public class RootTree : Tree
-       {
-               public const int MonodocVersion = 2;
-               const string RootNamespace = "root:/";
-               string basedir;
-               static List<string> uncompiledHelpSourcePaths = new List<string>();
-               HashSet<string> loadedSourceFiles = new HashSet<string>();
-               List<HelpSource> helpSources = new List<HelpSource>();
-               Dictionary<string, Node> nameToNode = new Dictionary<string, Node>();
-               Dictionary<string, HelpSource> nameToHelpSource = new Dictionary<string, HelpSource>();
-
-               public IList<HelpSource> HelpSources {
-                       get {
-                               return this.helpSources.AsReadOnly();
-                       }
-               }
-
-               public DateTime LastHelpSourceTime {
-                       get;
-                       set;
-               }
-
-               static bool IsUnix {
-                       get {
-                               int platform = (int)Environment.OSVersion.Platform;
-                               return platform == 4 || platform == 128 || platform == 6;
-                       }
-               }
-
-               RootTree () : base (null, "Mono Documentation", "root:")
-               {
-                       base.RootNode.EnsureNodes();
-                       this.LastHelpSourceTime = DateTime.Now;
-               }
-
-               public static void AddUncompiledSource (string path)
-               {
-                       uncompiledHelpSourcePaths.Add (path);
-               }
-
-               public static RootTree LoadTree ()
-               {
-                       return RootTree.LoadTree (RootTree.ProbeBaseDirectories ());
-               }
-
-               static string ProbeBaseDirectories ()
-               {
-                       string result = ".";
-                       try {
-                               result = Settings.Get ("docPath") ?? ".";
-                       } catch {}
-
-                       return result;
-               }
-
-               public static RootTree LoadTree (string basedir, bool includeExternal = true)
-               {
-                       if (string.IsNullOrEmpty (basedir))
-                               throw new ArgumentNullException ("basedir");
-                       if (!Directory.Exists (basedir))
-                               throw new ArgumentException ("basedir", string.Format ("Base documentation directory at '{0}' doesn't exist", basedir));
-
-                       XmlDocument xmlDocument = new XmlDocument ();
-                       string filename = Path.Combine (basedir, "monodoc.xml");
-                       xmlDocument.Load (filename);
-                       IEnumerable<string> sourceFiles = Directory.EnumerateFiles (Path.Combine (basedir, "sources"), "*.source");
-                       if (includeExternal)
-                               sourceFiles = sourceFiles.Concat (RootTree.ProbeExternalDirectorySources ());
-                       return RootTree.LoadTree (basedir, xmlDocument, sourceFiles);
-               }
-
-               static IEnumerable<string> ProbeExternalDirectorySources ()
-               {
-                       IEnumerable<string> enumerable = Enumerable.Empty<string> ();
-                       try {
-                               string path = Settings.Get ("docExternalPath");
-                               enumerable = enumerable.Concat (System.IO.Directory.EnumerateFiles (path, "*.source"));
-                       }
-                       catch {}
-
-                       if (Directory.Exists ("/Library/Frameworks/Mono.framework/External/monodoc"))
-                               enumerable = enumerable.Concat (Directory.EnumerateFiles ("/Library/Frameworks/Mono.framework/External/monodoc", "*.source"));
-                       return enumerable;
-               }
-
-               public static RootTree LoadTree (string indexDir, XmlDocument docTree, IEnumerable<string> sourceFiles)
-               {
-                       if (docTree == null) {
-                               docTree = new XmlDocument ();
-                               using  (Stream manifestResourceStream = typeof (RootTree).Assembly.GetManifestResourceStream ("monodoc.xml")) {
-                                       docTree.Load (manifestResourceStream);
-                               }
-                       }
-
-                       sourceFiles =  (sourceFiles ?? new string[0]);
-                       RootTree rootTree = new RootTree ();
-                       rootTree.basedir = indexDir;
-                       XmlNodeList xml_node_list = docTree.SelectNodes ("/node/node");
-                       rootTree.nameToNode["root"] = rootTree.RootNode;
-                       rootTree.nameToNode["libraries"] = rootTree.RootNode;
-                       rootTree.Populate (rootTree.RootNode, xml_node_list);
-
-                       if (rootTree.LookupEntryPoint ("various") == null) {
-                               Console.Error.WriteLine ("No 'various' doc node! Check monodoc.xml!");
-                               Node rootNode = rootTree.RootNode;
-                       }
-
-                       foreach (string current in sourceFiles)
-                               rootTree.AddSourceFile (current);
-
-                       foreach (string path in uncompiledHelpSourcePaths) {
-                               var hs = new Providers.EcmaUncompiledHelpSource (path);
-                               hs.RootTree = rootTree;
-                               rootTree.helpSources.Add (hs);
-                               string epath = "extra-help-source-" + hs.Name;
-                               Node hsn = rootTree.RootNode.CreateNode (hs.Name, "root:/" + epath);
-                               rootTree.nameToHelpSource [epath] = hs;
-                               hsn.EnsureNodes ();
-                               foreach (Node n in hs.Tree.RootNode.Nodes)
-                                       hsn.AddNode (n);
-                       }
-
-                       RootTree.PurgeNode (rootTree.RootNode);
-                       rootTree.RootNode.Sort ();
-                       return rootTree;
-               }
-
-               public void AddSource (string sourcesDir)
-               {
-                       IEnumerable<string> enumerable = Directory.EnumerateFiles (sourcesDir, "*.source");
-                       foreach (string current in enumerable)
-                               if (!this.AddSourceFile (current))
-                                       Console.Error.WriteLine ("Error: Could not load source file {0}", current);
-               }
-
-               public bool AddSourceFile (string sourceFile)
-               {
-                       if (this.loadedSourceFiles.Contains (sourceFile))
-                               return false;
-
-                       Node node = this.LookupEntryPoint ("various") ?? base.RootNode;
-                       XmlDocument xmlDocument = new XmlDocument ();
-                       try {
-                               xmlDocument.Load (sourceFile);
-                       } catch {
-                               bool result = false;
-                               return result;
-                       }
-
-                       XmlNodeList extra_nodes = xmlDocument.SelectNodes ("/monodoc/node");
-                       if (extra_nodes.Count > 0)
-                               this.Populate (node, extra_nodes);
-
-                       XmlNodeList sources = xmlDocument.SelectNodes ("/monodoc/source");
-                       if (sources == null) {
-                               Console.Error.WriteLine ("Error: No <source> section found in the {0} file", sourceFile);
-                               return false;
-                       }
-
-                       loadedSourceFiles.Add (sourceFile);
-                       foreach (XmlNode xmlNode in sources) {
-                               XmlAttribute a = xmlNode.Attributes["provider"];
-                               if (a == null) {
-                                       Console.Error.WriteLine ("Error: no provider in <source>");
-                                       continue;
-                               }
-                               string provider = a.InnerText;
-                               a = xmlNode.Attributes["basefile"];
-                               if (a == null) {
-                                       Console.Error.WriteLine ("Error: no basefile in <source>");
-                                       continue;
-                               }
-                               string basefile = a.InnerText;
-                               a = xmlNode.Attributes["path"];
-                               if (a == null) {
-                                       Console.Error.WriteLine ("Error: no path in <source>");
-                                       continue;
-                               }
-                               string path = a.InnerText;
-                               string basefilepath = Path.Combine (Path.GetDirectoryName (sourceFile), basefile);
-                               HelpSource helpSource = RootTree.GetHelpSource (provider, basefilepath);
-                               if (helpSource != null) {
-                                       helpSource.RootTree = this;
-                                       this.helpSources.Add (helpSource);
-                                       this.nameToHelpSource[path] = helpSource;
-                                       Node node2 = this.LookupEntryPoint (path);
-                                       if (node2 == null) {
-                                               Console.Error.WriteLine ("node `{0}' is not defined on the documentation map", path);
-                                               node2 = node;
-                                       }
-                                       foreach (Node current in helpSource.Tree.RootNode.Nodes) {
-                                               node2.AddNode (current);
-                                       }
-                                       node2.Sort ();
-                               }
-                       }
-                       return true;
-               }
-
-               static bool PurgeNode (Node node)
-               {
-                       bool result = false;
-                       if (!node.Documented)
-                       {
-                               List<Node> list = new List<Node> ();
-                               foreach (Node current in node.Nodes)
-                               {
-                                       bool flag = RootTree.PurgeNode (current);
-                                       if (flag)
-                                       {
-                                               list.Add (current);
-                                       }
-                               }
-                               result =  (node.Nodes.Count == list.Count);
-                               foreach (Node current2 in list)
-                               {
-                                       node.DeleteNode (current2);
-                               }
-                       }
-                       return result;
-               }
-
-               public static string[] GetSupportedFormats ()
-               {
-                       return new string[]
-                       {
-                               "ecma",
-                               "ecmaspec",
-                               "error",
-                               "man",
-                               "xhtml"
-                       };
-               }
-
-               public static HelpSource GetHelpSource (string provider, string basefilepath)
-               {
-                       HelpSource result;
-                       try {
-                               switch (provider) {
-                               case "xhtml":
-                               case "hb":
-                                       result = new XhtmlHelpSource (basefilepath, false);
-                                       break;
-                               case "man":
-                                       result = new ManHelpSource (basefilepath, false);
-                                       break;
-                               case "error":
-                                       result = new ErrorHelpSource (basefilepath, false);
-                                       break;
-                               case "ecmaspec":
-                                       result = new EcmaSpecHelpSource (basefilepath, false);
-                                       break;
-                               case "ecma":
-                                       result = new EcmaHelpSource (basefilepath, false);
-                                       break;
-                               default:
-                                       Console.Error.WriteLine ("Error: Unknown provider specified: {0}", provider);
-                                       result = null;
-                                       break;
-                               }
-                       } catch (FileNotFoundException) {
-                               Console.Error.WriteLine ("Error: did not find one of the files in sources/" + basefilepath);
-                               result = null;
-                       }
-                       return result;
-               }
-
-               public static Provider GetProvider (string provider, params string[] basefilepaths)
-               {
-                       switch (provider) {
-                       case "ecma":
-                               return new EcmaProvider (basefilepaths[0]);
-                       case "ecmaspec":
-                               return new EcmaSpecProvider (basefilepaths[0]);
-                       case "error":
-                               return new ErrorProvider (basefilepaths[0]);
-                       case "man":
-                               return new ManProvider (basefilepaths);
-                       case "xhml":
-                       case "hb":
-                               return new XhtmlProvider (basefilepaths[0]);
-                       }
-
-                       throw new NotSupportedException (provider);
-               }
-
-               void Populate (Node parent, XmlNodeList xml_node_list)
-               {
-                       foreach (XmlNode xmlNode in xml_node_list) {
-                               XmlAttribute e = xmlNode.Attributes["parent"];
-                               Node parent2 = null;
-                               if (e != null && this.nameToNode.TryGetValue (e.InnerText, out parent2)) {
-                                       xmlNode.Attributes.Remove (e);
-                                       Populate (parent2, xmlNode.SelectNodes ("."));
-                                       continue;
-                               }
-                               e = xmlNode.Attributes["label"];
-                               if (e == null) {
-                                       Console.Error.WriteLine ("`label' attribute missing in <node>");
-                                       continue;
-                               }
-                               string label = e.InnerText;
-                               e = xmlNode.Attributes["name"];
-                               if (e == null) {
-                                       Console.Error.WriteLine ("`name' attribute missing in <node>");
-                                       continue;
-                               }
-                               string name = e.InnerText;
-                               Node orCreateNode = parent.GetOrCreateNode (label, "root:/" + name);
-                               orCreateNode.EnsureNodes ();
-                               this.nameToNode[name] = orCreateNode;
-                               XmlNodeList xmlNodeList = xmlNode.SelectNodes ("./node");
-                               if (xmlNodeList != null) {
-                                       this.Populate (orCreateNode, xmlNodeList);
-                               }
-                       }
-               }
-
-               public Node LookupEntryPoint (string name)
-               {
-                       Node result = null;
-                       if (!this.nameToNode.TryGetValue (name, out result)) {
-                               result = null;
-                       }
-                       return result;
-               }
-
-               public TOutput RenderUrl<TOutput> (string url, IDocGenerator<TOutput> generator, HelpSource hintSource = null)
-               {
-                       Node dummy;
-                       return RenderUrl<TOutput> (url, generator, out dummy, hintSource);
-               }
-
-               public TOutput RenderUrl<TOutput> (string url, IDocGenerator<TOutput> generator, out Node node, HelpSource hintSource = null)
-               {
-                       node = null;
-                       string internalId = null;
-                       HelpSource hs = GetHelpSourceAndIdForUrl (url, hintSource, out internalId, out node);
-                       return generator.Generate (hs, internalId);
-               }
-
-               public HelpSource GetHelpSourceAndIdForUrl (string url, out string internalId)
-               {
-                       Node dummy;
-                       return GetHelpSourceAndIdForUrl (url, out internalId, out dummy);
-               }
-
-               public HelpSource GetHelpSourceAndIdForUrl (string url, out string internalId, out Node node)
-               {
-                       return GetHelpSourceAndIdForUrl (url, null, out internalId, out node);
-               }
-
-               public HelpSource GetHelpSourceAndIdForUrl (string url, HelpSource hintSource, out string internalId, out Node node)
-               {
-                       node = null;
-                       internalId = null;
-
-                       if (url.StartsWith ("root:/", StringComparison.OrdinalIgnoreCase))
-                               return this.GetHelpSourceAndIdFromName (url.Substring ("root:/".Length), out internalId, out node);
-
-                       HelpSource helpSource = hintSource;
-                       if (helpSource == null || string.IsNullOrEmpty (internalId = helpSource.GetInternalIdForUrl (url, out node))) {
-                               helpSource = null;
-                               foreach (var hs in helpSources.Where (h => h.CanHandleUrl (url))) {
-                                       if (!string.IsNullOrEmpty (internalId = hs.GetInternalIdForUrl (url, out node))) {
-                                               helpSource = hs;
-                                               break;
-                                       }
-                               }
-                       }
-
-                       return helpSource;
-               }
-
-               public HelpSource GetHelpSourceAndIdFromName (string name, out string internalId, out Node node)
-               {
-                       internalId = "root:";
-                       node = this.LookupEntryPoint (name);
-
-                       return node == null ? null : node.Nodes.Select (n => n.Tree.HelpSource).Where (hs => hs != null).Distinct ().FirstOrDefault ();
-               }
-
-               public HelpSource GetHelpSourceFromId (int id)
-               {
-                       return  (id < 0 || id >= this.helpSources.Count) ? null : this.helpSources[id];
-               }
-
-               public Stream GetImage (string url)
-               {
-                       if (url.StartsWith ("source-id:", StringComparison.OrdinalIgnoreCase)) {
-                               string text = url.Substring (10);
-                               int num = text.IndexOf (":");
-                               string text2 = text.Substring (0, num);
-                               int id = 0;
-                               try {
-                                       id = int.Parse (text2);
-                               } catch {
-                                       Console.Error.WriteLine ("Failed to parse source-id url: {0} `{1}'", url, text2);
-                                       return null;
-                               }
-                               HelpSource helpSourceFromId = this.GetHelpSourceFromId (id);
-                               return helpSourceFromId.GetImage (text.Substring (num + 1));
-                       }
-                       Assembly assembly = Assembly.GetAssembly (typeof (RootTree));
-                       return assembly.GetManifestResourceStream (url);
-               }
-
-               public IndexReader GetIndex ()
-               {
-                       try {
-                               string text = Path.Combine (this.basedir, "monodoc.index");
-                               if (File.Exists (text))
-                                       return IndexReader.Load (text);
-
-                               text = Path.Combine (Settings.Get ("monodocIndexDirectory"), "monodoc.index");
-                               return IndexReader.Load (text);
-                       } catch {
-                               return null;
-                       }
-               }
-
-               public static void MakeIndex ()
-               {
-                       RootTree rootTree = RootTree.LoadTree ();
-                       rootTree.GenerateIndex ();
-               }
-
-               public void GenerateIndex ()
-               {
-                       IndexMaker indexMaker = new IndexMaker ();
-                       foreach (HelpSource current in this.helpSources)
-                               current.PopulateIndex (indexMaker);
-                       string text = Path.Combine (this.basedir, "monodoc.index");
-                       try {
-                               indexMaker.Save (text);
-                       } catch (UnauthorizedAccessException) {
-                               text = Path.Combine (Settings.Get ("docPath"), "monodoc.index");
-                               try {
-                                       indexMaker.Save (text);
-                               } catch (UnauthorizedAccessException) {
-                                       Console.WriteLine ("Unable to write index file in {0}", Path.Combine (Settings.Get ("docPath"), "monodoc.index"));
-                                       return;
-                               }
-                       }
-                       if (RootTree.IsUnix)
-                               RootTree.chmod (text, 420);
-
-                       Console.WriteLine ("Documentation index at {0} updated", text);
-               }
-
-               public SearchableIndex GetSearchIndex ()
-               {
-                       try {
-                               string text = Path.Combine (this.basedir, "search_index");
-                               if (System.IO.Directory.Exists (text))
-                                       return SearchableIndex.Load (text);
-                               text = Path.Combine (Settings.Get ("docPath"), "search_index");
-                               return SearchableIndex.Load (text);
-                       } catch {
-                               return null;
-                       }
-               }
-
-               public static void MakeSearchIndex ()
-               {
-                       RootTree rootTree = RootTree.LoadTree ();
-                       rootTree.GenerateSearchIndex ();
-               }
-
-               public void GenerateSearchIndex ()
-               {
-                       Console.WriteLine ("Loading the monodoc tree...");
-                       string text = Path.Combine (this.basedir, "search_index");
-                       IndexWriter indexWriter;
-                       var analyzer = new StandardAnalyzer (Lucene.Net.Util.Version.LUCENE_CURRENT);
-                       var directory = Lucene.Net.Store.FSDirectory.Open (text);
-
-                       try {
-                               if (!Directory.Exists (text))
-                                       Directory.CreateDirectory (text);
-                               indexWriter = new IndexWriter (directory, analyzer, true, IndexWriter.MaxFieldLength.LIMITED);
-                       } catch (UnauthorizedAccessException) {
-                               try {
-                                       text = Path.Combine (Settings.Get ("docPath"), "search_index");
-                                       if (!Directory.Exists (text))
-                                               Directory.CreateDirectory (text);
-                                       indexWriter = new IndexWriter (directory, analyzer, true, IndexWriter.MaxFieldLength.LIMITED);
-                               } catch (UnauthorizedAccessException) {
-                                       Console.WriteLine ("You don't have permissions to write on " + text);
-                                       return;
-                               }
-                       }
-                       Console.WriteLine ("Collecting and adding documents...");
-                       foreach (HelpSource current in this.helpSources) {
-                               current.PopulateSearchableIndex (indexWriter);
-                       }
-                       Console.WriteLine ("Closing...");
-                       indexWriter.Optimize ();
-                       indexWriter.Close ();
-               }
-
-               [DllImport ("libc")]
-               static extern int chmod (string filename, int mode);
-       }
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/SearchableDocument.cs b/mcs/tools/monkeydoc/Monkeydoc/SearchableDocument.cs
deleted file mode 100644 (file)
index eebcc3a..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-//
-//
-// SearchableDocument.cs: Abstracts our model of document from the Lucene Document 
-//
-// Author: Mario Sopena
-//
-using Lucene.Net.Documents;
-
-namespace MonkeyDoc
-{
-       struct SearchableDocument
-       {
-               public string Title {
-                       get; set;
-               }
-
-               public string Url {
-                       get; set;
-               }
-
-               public string FullTitle {
-                       get; set;
-               }
-
-               public string HotText {
-                       get; set;
-               }
-
-               public string Text {
-                       get; set;
-               }
-
-               public string Examples {
-                       get; set;
-               }
-
-               public SearchableDocument Reset ()
-               {
-                       Title = Url = FullTitle = HotText = Text = Examples = null;
-                       return this;
-               }
-
-               public Document LuceneDoc {
-                       get {
-                               Document doc = new Document ();
-                               doc.Add (UnIndexed ("title", Title));
-                               doc.Add (UnIndexed ("url", Url));
-                               doc.Add (UnIndexed ("fulltitle", FullTitle ?? string.Empty));
-                               doc.Add (UnStored ("hottext", HotText));
-                               doc.Add (UnStored ("text", Text));
-                               doc.Add (UnStored ("examples", Examples));
-                               return doc;
-                       }
-               }
-
-               static Field UnIndexed(System.String name, System.String value_Renamed)
-               {
-                       return new Field(name, value_Renamed, Field.Store.YES, Field.Index.NO);
-               }
-
-               static Field UnStored(System.String name, System.String value_Renamed)
-               {
-                       return new Field(name, value_Renamed, Field.Store.NO, Field.Index.ANALYZED);
-               }
-       }
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/SearchableIndex.cs b/mcs/tools/monkeydoc/Monkeydoc/SearchableIndex.cs
deleted file mode 100644 (file)
index 7eb24fe..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-//
-//
-// SearchableIndex.cs: Index that uses Lucene to search through the docs 
-//
-// Author: Mario Sopena
-//
-
-using System;
-using System.IO;
-using System.Collections.Generic;
-// Lucene imports
-using Lucene.Net.Index;
-using Lucene.Net.Documents;
-using Lucene.Net.Analysis;
-using Lucene.Net.Analysis.Standard;
-using Lucene.Net.Search;
-using Lucene.Net.QueryParsers;
-using Lucene.Net.Store;
-
-namespace MonkeyDoc
-{
-       public class SearchableIndex 
-       {
-               const int maxSearchCount = 30;
-
-               IndexSearcher searcher;
-               string dir;
-
-               public string Dir {
-                       get { 
-                               if (dir == null)
-                                       dir = "search_index";
-                               return dir;
-                       }
-                       set { dir = value; }
-               }
-
-               public static SearchableIndex Load (string dir)
-               {
-                       SearchableIndex s = new SearchableIndex ();
-                       s.dir = dir;
-                       try {
-                               //s.searcher = new IndexSearcher (dir);
-                               // TODO: parametrize that depending if we run on the desktop (low footprint) or the server (use RAMDirectory for instance)
-                               s.searcher = new IndexSearcher (FSDirectory.Open (dir));
-                       } catch (IOException) {
-                               Console.WriteLine ("Index nonexistent or in bad format");
-                               return null;
-                       }
-                       return s;
-               }
-               
-               public Result Search (string term)
-               {
-                       return Search (term, maxSearchCount);
-               }
-
-               public Result Search (string term, int count)
-               {
-                       return Search (term, count, 0);
-               }
-
-               public Result Search (string term, int count, int start) {
-                       try {
-                               term = term.ToLower ();
-                               Term htTerm = new Term ("hottext", term);
-                               Query qq1 = new FuzzyQuery (htTerm);
-                               Query qq2 = new TermQuery (htTerm);
-                               qq2.Boost = 10f;
-                               Query qq3 = new PrefixQuery (htTerm);
-                               qq3.Boost = 10f;
-                               DisjunctionMaxQuery q1 = new DisjunctionMaxQuery (0f);
-                               q1.Add (qq1);
-                               q1.Add (qq2);
-                               q1.Add (qq3);
-                               Query q2 = new TermQuery (new Term ("text", term));
-                               q2.Boost = 3f;
-                               Query q3 = new TermQuery (new Term ("examples", term));
-                               q3.Boost = 3f;
-                               DisjunctionMaxQuery q = new DisjunctionMaxQuery (0f);
-
-                               q.Add (q1);
-                               q.Add (q2);
-                               q.Add (q3);
-                       
-                               TopDocs top = SearchInternal (q, count, start);
-                               Result r = new Result (term, searcher, top.ScoreDocs);
-                               return r;
-                       } catch (IOException) {
-                               Console.WriteLine ("No index in {0}", dir);
-                               return null;
-                       }
-               }
-
-               TopDocs SearchInternal (Query q, int count, int start)
-               {
-                       // Easy path that doesn't involve creating a Collector ourselves
-                       // watch for Lucene.NET improvement on that (like searcher.SearchAfter)
-                       if (start == 0)
-                               return searcher.Search (q, count);
-
-                       var weight = searcher.CreateWeight (q); // TODO: reuse weight instead of query
-                       var collector = TopScoreDocCollector.Create (start + count + 1, false);
-                       searcher.Search (q, collector);
-
-                       return collector.TopDocs (start, count);
-               }
-
-               public Result FastSearch (string term, int number)
-               {
-                       try {
-                               term = term.ToLower ();
-                               Query q1 = new TermQuery (new Term ("hottext", term));
-                               Query q2 = new PrefixQuery (new Term ("hottext", term));
-                               q2.Boost = 0.5f;
-                               DisjunctionMaxQuery q = new DisjunctionMaxQuery (0f);
-                               q.Add (q1);
-                               q.Add (q2);
-                               TopDocs top = searcher.Search (q, number);
-                               return new Result (term, searcher, top.ScoreDocs);
-                       } catch (IOException) {
-                               Console.WriteLine ("No index in {0}", dir);
-                               return null;
-                       }
-               }
-       }
-
-       //
-       // An object representing the search term with the results
-       // 
-       public class Result {
-               string term;
-               Searcher searcher;
-               ScoreDoc[] docs;
-
-               public string Term {
-                       get { return term;}
-               }
-
-               public int Count {
-                       get { return docs.Length; }
-               }
-
-               public Document this [int i] {
-                       get { return searcher.Doc (docs[i].Doc); }
-               }
-       
-               public string GetTitle (int i) 
-               {
-                       Document d = this[i];
-                       return d == null ? string.Empty : d.Get ("title");
-               }
-
-               public string GetUrl (int i)
-               {
-                       Document d = this[i];
-                       return d == null ? string.Empty : d.Get ("url");
-               }
-
-               public string GetFullTitle (int i)
-               {
-                       Document d = this[i];
-                       return d == null ? string.Empty : d.Get ("fulltitle");
-               }
-
-               public float Score (int i)
-               {
-                       return docs[i].Score;
-               }
-
-               public Result (string Term, Searcher searcher, ScoreDoc[] docs) 
-               {
-                       this.term = Term;
-                       this.searcher = searcher;
-                       this.docs = docs;
-               }
-       }
-}
-
diff --git a/mcs/tools/monkeydoc/Monkeydoc/Tree.cs b/mcs/tools/monkeydoc/Monkeydoc/Tree.cs
deleted file mode 100644 (file)
index a9b3367..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-using System;
-using System.IO;
-using System.Text;
-using System.Linq;
-using System.Xml;
-using System.Collections.Generic;
-
-namespace MonkeyDoc
-{
-       /// <summary>
-       ///    This tree is populated by the documentation providers, or populated
-       ///    from a binary encoding of the tree.  The format of the tree is designed
-       ///    to minimize the need to load it in full.
-       /// </summary>
-
-       /* Ideally this class should also be abstracted to let user have something
-        * else than a file as a backing store, a database for instance
-        */
-       public class Tree
-       {
-               public readonly HelpSource HelpSource;
-       
-               FileStream InputStream;
-               BinaryReader InputReader;
-
-               // This is the node which contains all the other node of the tree
-               Node rootNode;
-
-               /// <summary>
-               ///   Load from file constructor
-               /// </summary>
-               public Tree (HelpSource hs, string filename)
-               {
-                       Encoding utf8 = new UTF8Encoding (false, true);
-
-                       if (!File.Exists (filename)){
-                               throw new FileNotFoundException ();
-                       }
-               
-                       InputStream = File.OpenRead (filename);
-                       InputReader = new BinaryReader (InputStream, utf8);
-                       byte [] sig = InputReader.ReadBytes (4);
-               
-                       if (!GoodSig (sig))
-                               throw new Exception ("Invalid file format");
-               
-                       InputStream.Position = 4;
-                       var position = InputReader.ReadInt32 ();
-                       rootNode = new Node (this, position);
-                       InflateNode (rootNode);
-
-                       HelpSource = hs;
-               }
-
-               /// <summary>
-               ///    Tree creation and merged tree constructor
-               /// </summary>
-               public Tree (HelpSource hs, string caption, string url) : this (hs, null, caption, url)
-               {
-               }
-
-               public Tree (HelpSource hs, Node parent, string caption, string element)
-               {
-                       HelpSource = hs;
-                       rootNode = parent == null ? new Node (this, caption, element) : new Node (parent, caption, element);
-               }
-
-               /// <summary>
-               ///    Saves the tree into the specified file using the help file format.
-               /// </summary>
-               public void Save (string file)
-               {
-                       Encoding utf8 = new UTF8Encoding (false, true);
-                       using (FileStream output = File.OpenWrite (file)){
-                               // Skip over the pointer to the first node.
-                               output.Position = 8;
-                       
-                               using (BinaryWriter writer = new BinaryWriter (output, utf8)) {
-                                       // Recursively dump
-                                       rootNode.Serialize (output, writer);
-
-                                       output.Position = 0;
-                                       writer.Write (new byte [] { (byte) 'M', (byte) 'o', (byte) 'H', (byte) 'P' });
-                                       writer.Write (rootNode.Address);
-                               }
-                       }
-               }
-
-               public Node RootNode {
-                       get {
-                               return rootNode;
-                       }
-               }
-
-               static bool GoodSig (byte [] sig)
-               {
-                       if (sig.Length != 4)
-                               return false;
-                       return sig [0] == (byte) 'M'
-                               && sig [1] == (byte) 'o'
-                           && sig [2] == (byte) 'H'
-                               && sig [3] == (byte) 'P';
-               }
-
-               public void InflateNode (Node baseNode)
-               {
-                       var address = baseNode.Address;
-                       if (address < 0)
-                               address = -address;
-
-                       InputStream.Position = address;
-                       baseNode.Deserialize (InputReader);
-               }
-       }
-
-       public static class TreeDumper
-       {
-               static int indent;
-
-               static void Indent ()
-               {
-                       for (int i = 0; i < indent; i++)
-                               Console.Write ("   ");
-               }
-       
-               public static void PrintTree (Node node)
-               {
-                       Indent ();
-                       Console.WriteLine ("{0},{1}\t[PublicUrl: {2}]", node.Element, node.Caption, node.PublicUrl);
-                       if (node.Nodes.Count == 0)
-                               return;
-
-                       indent++;
-                       foreach (Node n in node.Nodes)
-                               PrintTree (n);
-                       indent--;
-               }
-
-               public static string ExportToTocXml (Node root, string title, string desc)
-               {
-                       if (root == null)
-                               throw new ArgumentNullException ("root");
-                       // Return a toc index of sub-nodes
-                       StringBuilder buf = new StringBuilder ();
-                       var writer = XmlWriter.Create (buf);
-                       writer.WriteStartElement ("toc");
-                       writer.WriteAttributeString ("title", title ?? string.Empty);
-                       writer.WriteElementString ("description", desc ?? string.Empty);
-                       writer.WriteStartElement ("list");
-                       foreach (Node n in root.Nodes) {
-                               writer.WriteStartElement ("item");
-                               writer.WriteAttributeString ("url", n.Element);
-                               writer.WriteValue (n.Caption);
-                               writer.WriteEndElement ();
-                       }
-                       writer.WriteEndElement ();
-                       writer.WriteEndElement ();
-                       writer.Flush ();
-                       writer.Close ();
-
-                       return buf.ToString ();
-               }
-       }
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/TypeUtils.cs b/mcs/tools/monkeydoc/Monkeydoc/TypeUtils.cs
deleted file mode 100644 (file)
index 2e75663..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-using System;
-
-namespace MonkeyDoc
-{
-       public static class TypeUtils
-       {
-               public static bool GetNamespaceAndType (string url, out string ns, out string type)
-               {
-                       int nsidx = -1;
-                       int numLt = 0;
-                       for (int i = 0; i < url.Length; ++i) {
-                               char c = url [i];
-                               switch (c) {
-                               case '<':
-                               case '{':
-                                       ++numLt;
-                                       break;
-                               case '>':
-                               case '}':
-                                       --numLt;
-                                       break;
-                               case '.':
-                                       if (numLt == 0)
-                                               nsidx = i;
-                                       break;
-                               }
-                       }
-
-                       if (nsidx == -1) {
-                               ns = null;
-                               type = null;
-                               return false;
-                       }
-                       ns = url.Substring (0, nsidx);
-                       type = url.Substring (nsidx + 1);
-               
-                       return true;
-               }
-       }
-}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/Monkeydoc/cache.cs b/mcs/tools/monkeydoc/Monkeydoc/cache.cs
deleted file mode 100644 (file)
index 1c26f05..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-using System;
-using System.Linq;
-using System.IO;
-using System.Configuration;
-using System.Collections.Specialized;
-using MonkeyDoc.Caches;
-
-namespace MonkeyDoc
-{
-       public enum DocEntity
-       {
-               Text,
-               Blob
-       }
-
-       public interface IDocCache : IDisposable
-       {
-               bool IsCached (string id);
-               bool CanCache (DocEntity entity);
-
-               Stream GetCachedStream (string id);
-               string GetCachedString (string id);
-
-               void CacheText (string id, string content);
-               void CacheText (string id, Stream stream);
-
-               void CacheBlob (string id, byte[] data);
-               void CacheBlob (string id, Stream stream);
-       }
-
-       public static class DocCacheHelper
-       {
-               static string cacheBaseDirectory;
-
-               static DocCacheHelper ()
-               {
-                       try {
-                               var cacheValues = Settings.Get ("cache").Split (',');
-                               if (cacheValues.Length == 2 && cacheValues[0].Equals ("file", StringComparison.Ordinal))
-                                       cacheBaseDirectory = cacheValues[1].Replace ("~", Environment.GetFolderPath (Environment.SpecialFolder.Personal));
-                       } catch {}
-               }
-
-               // Use configuration option to query for cache directory, if it doesn't exist we instantiate a nullcache
-               public static IDocCache GetDefaultCache (string name)
-               {
-                       if (cacheBaseDirectory == null)
-                               return new NullCache ();
-
-                       return new FileCache (Path.Combine (cacheBaseDirectory, name));
-               }
-       }
-}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/Monkeydoc/caches/FileCache.cs b/mcs/tools/monkeydoc/Monkeydoc/caches/FileCache.cs
deleted file mode 100644 (file)
index 333f33b..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-using System;
-using System.IO;
-
-namespace MonkeyDoc.Caches
-{
-       public class FileCache : IDocCache
-       {
-               string baseCacheDir;
-
-               public FileCache (string baseCacheDir)
-               {
-                       this.baseCacheDir = baseCacheDir;
-                       if (!Directory.Exists (baseCacheDir))
-                               Directory.CreateDirectory (baseCacheDir);
-               }
-
-               public bool IsCached (string id)
-               {
-                       return File.Exists (MakePath (id));
-               }
-
-               public bool CanCache (DocEntity entity)
-               {
-                       return true;
-               }
-
-               public Stream GetCachedStream (string id)
-               {
-                       return File.OpenRead (MakePath (id));
-               }
-
-               public string GetCachedString (string id)
-               {
-                       return File.ReadAllText (MakePath (id));
-               }
-
-               public void CacheText (string id, string content)
-               {
-                       File.WriteAllText (MakePath (id), content);
-               }
-
-               public void CacheText (string id, Stream stream)
-               {
-                       using (var file = File.OpenWrite (MakePath (id)))
-                               stream.CopyTo (file);
-               }
-
-               public void CacheBlob (string id, byte[] data)
-               {
-                       File.WriteAllBytes (MakePath (id), data);
-               }
-
-               public void CacheBlob (string id, Stream stream)
-               {
-                       using (var file = File.OpenWrite (MakePath (id)))
-                               stream.CopyTo (file);
-               }
-
-               string MakePath (string id)
-               {
-                       id = id.Replace (Path.DirectorySeparatorChar, '_');
-                       return Path.Combine (baseCacheDir, id);
-               }
-
-               public void Dispose ()
-               {
-                       if (!Directory.Exists (baseCacheDir))
-                               return;
-
-                       try {
-                               Directory.Delete (baseCacheDir, true);
-                       } catch {}
-               }
-       }
-}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/Monkeydoc/caches/NullCache.cs b/mcs/tools/monkeydoc/Monkeydoc/caches/NullCache.cs
deleted file mode 100644 (file)
index 1514d66..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-using System;
-using System.IO;
-
-namespace MonkeyDoc.Caches
-{
-       // This is basically a no-cache implementation
-       public class NullCache : IDocCache
-       {
-               public bool IsCached (string id)
-               {
-                       return false;
-               }
-
-               public bool CanCache (DocEntity entity)
-               {
-                       return false;
-               }
-
-               public Stream GetCachedStream (string id)
-               {
-                       return null;
-               }
-
-               public string GetCachedString (string id)
-               {
-                       return null;
-               }
-
-               public void CacheText (string id, string content)
-               {
-
-               }
-
-               public void CacheText (string id, Stream stream)
-               {
-
-               }
-
-               public void CacheBlob (string id, byte[] data)
-               {
-
-               }
-
-               public void CacheBlob (string id, Stream stream)
-               {
-
-               }
-
-               public void Dispose ()
-               {
-                       
-               }
-       }
-}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/Monkeydoc/generator.cs b/mcs/tools/monkeydoc/Monkeydoc/generator.cs
deleted file mode 100644 (file)
index f0949b9..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-using System;
-
-namespace MonkeyDoc
-{
-       // All type of documents that a generator may find as input
-       public enum DocumentType {
-               EcmaXml, // Our main monodoc format
-               EcmaSpecXml,
-               Man,
-               AddinXml,
-               MonoBook, // This is mostly XHTML already, just need a tiny bit of processing
-               Html,
-               TocXml, // Used by help source displaying some kind of toc of the content they host
-               PlainText,
-               ErrorXml
-       }
-
-       /* This interface defines a set of transformation engine
-        * that convert multiple documentation source to a single output format
-        */
-       public interface IDocGenerator<TOutput>
-       {
-               // This method is responsible for finding out the documentation type
-               // for the given ID and use the right engine internally
-               TOutput Generate (HelpSource hs, string internalId);
-       }
-}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/Monkeydoc/generators/HtmlGenerator.cs b/mcs/tools/monkeydoc/Monkeydoc/generators/HtmlGenerator.cs
deleted file mode 100644 (file)
index d7eeeb8..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-using System;
-using System.IO;
-using System.Text;
-using System.Linq;
-using System.Collections.Generic;
-
-using MonkeyDoc;
-
-namespace MonkeyDoc.Generators
-{
-       using Html;
-
-       interface IHtmlExporter
-       {
-               string CssCode { get; }
-               string Export (Stream input, Dictionary<string, string> extras);
-               string Export (string input, Dictionary<string, string> extras);
-       }
-
-       public class HtmlGenerator : IDocGenerator<string>
-       {
-               const string cachePrefix = "htmlcached#";
-
-               static string css_code;
-
-               IDocCache defaultCache;
-               static Dictionary<DocumentType, IHtmlExporter> converters;
-
-               static HtmlGenerator ()
-               {
-                       converters = new Dictionary<DocumentType, IHtmlExporter> {
-                               { DocumentType.EcmaXml, new Ecma2Html () },
-                               { DocumentType.Man, new Man2Html () },
-                               { DocumentType.TocXml, new Toc2Html () },
-                               { DocumentType.EcmaSpecXml, new Ecmaspec2Html () },
-                               { DocumentType.ErrorXml, new Error2Html () },
-                               { DocumentType.Html, new Idem () },
-                               { DocumentType.MonoBook, new MonoBook2Html () },
-                               { DocumentType.AddinXml, new Addin2Html () },
-                               { DocumentType.PlainText, new Idem () },
-                       };
-               }
-
-               public HtmlGenerator (IDocCache defaultCache)
-               {
-                       this.defaultCache = defaultCache;
-               }
-
-               public string Generate (HelpSource hs, string id)
-               {
-                       if (hs == null || string.IsNullOrEmpty (id))
-                               return MakeHtmlError (string.Format ("Your request has found no candidate provider [hs=\"{0}\", id=\"{1}\"]",
-                                                                    hs == null ? "(null)" : hs.Name, id ?? "(null)"));
-                       var cache = defaultCache ?? hs.Cache;
-                       if (cache != null && cache.IsCached (MakeCacheKey (hs, id, null)))
-                               return cache.GetCachedString (MakeCacheKey (hs, id, null));
-
-                       IEnumerable<string> parts;
-                       if (hs.IsMultiPart (id, out parts))
-                               return GenerateMultiPart (hs, parts, id);
-
-                       if (hs.IsRawContent (id))
-                               return hs.GetText (id) ?? string.Empty;
-
-                       Dictionary<string, string> extraParams = null;
-                       DocumentType type = hs.GetDocumentTypeForId (id, out extraParams);
-                       if (cache != null && extraParams != null && cache.IsCached (MakeCacheKey (hs, id, extraParams)))
-                               return cache.GetCachedString (MakeCacheKey (hs, id, extraParams));
-
-                       IHtmlExporter exporter;
-                       if (!converters.TryGetValue (type, out exporter))
-                               return MakeHtmlError (string.Format ("Input type '{0}' not supported",
-                                                                    type.ToString ()));
-                       var result = hs.IsGeneratedContent (id) ? 
-                               exporter.Export (hs.GetCachedText (id), extraParams) :
-                               exporter.Export (hs.GetCachedHelpStream (id), extraParams);
-
-                       if (cache != null)
-                               cache.CacheText (MakeCacheKey (hs, id, extraParams), result);
-                       return result;
-               }
-
-               string GenerateMultiPart (HelpSource hs, IEnumerable<string> ids, string originalId)
-               {
-                       var sb = new StringBuilder ();
-                       foreach (var id in ids)
-                               sb.AppendLine (Generate (hs, id));
-
-                       var cache = defaultCache ?? hs.Cache;
-                       if (cache != null)
-                               cache.CacheText (MakeCacheKey (hs, originalId, null), sb.ToString ());
-                       return sb.ToString ();
-               }
-
-               public static string InlineCss {
-                       get {
-                               if (css_code != null)
-                                       return css_code;
-
-                               System.Reflection.Assembly assembly = System.Reflection.Assembly.GetAssembly (typeof (HtmlGenerator));
-                               Stream str_css = assembly.GetManifestResourceStream ("base.css");
-                               StringBuilder sb = new StringBuilder ((new StreamReader (str_css)).ReadToEnd());
-                               sb.Replace ("@@FONT_FAMILY@@", "Sans Serif");
-                               sb.Replace ("@@FONT_SIZE@@", "100%");
-                               css_code = sb.ToString () + converters.Values
-                                       .Select (c => c.CssCode)
-                                       .Where (css => !string.IsNullOrEmpty (css))
-                                       .DefaultIfEmpty (string.Empty)
-                                       .Aggregate (string.Concat);
-                               return css_code;
-                       }
-                       set { 
-                               css_code = value;
-                       }
-               }
-
-               string MakeHtmlError (string error)
-               {
-                       return string.Format ("<html><head></head><body><p>{0}</p></body></html>", error);
-               }
-
-               string MakeCacheKey (HelpSource hs, string page, IDictionary<string,string> extraParams)
-               {
-                       var key = cachePrefix + hs.SourceID + page;
-                       if (extraParams != null && extraParams.Count > 0) {
-                               var paramPart = string.Join ("-", extraParams.Select (kvp => kvp.Key + kvp.Value));
-                               key += '_' + paramPart;
-                       }
-                       return key;
-               }
-       }
-}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/Monkeydoc/generators/RawGenerator.cs b/mcs/tools/monkeydoc/Monkeydoc/generators/RawGenerator.cs
deleted file mode 100644 (file)
index c1e4bb2..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-using System;
-using System.IO;
-using System.Text;
-using System.Linq;
-using System.Collections.Generic;
-
-using MonkeyDoc;
-
-namespace MonkeyDoc.Generators
-{
-       /// <summary>
-       /// This generators returns the raw content of the HelpSource without any transformation
-       /// </summary>
-       public class RawGenerator : IDocGenerator<string>
-       {
-               public string Generate (HelpSource hs, string id)
-               {
-                       if (hs == null || string.IsNullOrEmpty (id))
-                               return null;
-
-                       IEnumerable<string> parts;
-                       if (hs.IsMultiPart (id, out parts))
-                               return GenerateMultiPart (hs, parts, id);
-
-                       if (hs.IsRawContent (id))
-                               return hs.GetText (id) ?? string.Empty;
-
-                       var result = hs.IsGeneratedContent (id) ? hs.GetCachedText (id) : new StreamReader (hs.GetCachedHelpStream (id)).ReadToEnd ();
-
-                       return result;
-               }
-
-               string GenerateMultiPart (HelpSource hs, IEnumerable<string> ids, string originalId)
-               {
-                       var sb = new StringBuilder ();
-                       foreach (var id in ids)
-                               sb.AppendLine (Generate (hs, id));
-                       return sb.ToString ();
-               }
-       }
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/generators/html/Addin2Html.cs b/mcs/tools/monkeydoc/Monkeydoc/generators/html/Addin2Html.cs
deleted file mode 100644 (file)
index 3d37482..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-using System;
-using System.IO;
-using System.Text;
-using System.Xml;
-using System.Xml.Xsl;
-using System.Xml.XPath;
-using System.Collections.Generic;
-
-namespace MonkeyDoc.Generators.Html
-{
-       public class Addin2Html : IHtmlExporter
-       {
-               public string CssCode {
-                       get {
-                               return string.Empty;
-                       }
-               }
-
-               public string Export (Stream stream, Dictionary<string, string> extraArgs)
-               {
-                       using (var reader = new StreamReader (stream))
-                               return Htmlize (GetAddin (reader, extraArgs["AddinID"]),
-                                               extraArgs["show"],
-                                               extraArgs["AddinID"],
-                                               extraArgs["FileID"],
-                                               extraArgs["NodeID"]);
-               }
-
-               public string Export (string input, Dictionary<string, string> extraArgs)
-               {
-                       return Htmlize (GetAddin (new StringReader (input), extraArgs["AddinID"]),
-                                       extraArgs["show"],
-                                       extraArgs["AddinID"],
-                                       extraArgs["FileID"],
-                                       extraArgs["NodeID"]);
-               }
-
-               XmlElement GetAddin (TextReader reader, string addinId)
-               {
-                       XmlDocument doc = new XmlDocument ();
-                       doc.Load (reader);
-                       XmlElement addin = (XmlElement) doc.SelectSingleNode ("Addins/Addin[@fullId='" + addinId + "']");
-                       return addin != null ? addin : null;
-               }
-
-               public string Htmlize (XmlElement addin, string urlType, string addinId, string fileId, string path)
-               {
-                       if (urlType == MonkeyDoc.Providers.AddinsHelpSource.AddinPrefix)
-                               return GetAddinTextFromUrl (addin, addinId, fileId);
-                       else if (urlType == MonkeyDoc.Providers.AddinsHelpSource.ExtensionPrefix)
-                               return GetExtensionTextFromUrl (addin, addinId, fileId, path);
-                       else if (urlType == MonkeyDoc.Providers.AddinsHelpSource.ExtensionNodePrefix)
-                               return GetExtensionNodeTextFromUrl (addin, addinId, fileId, path);
-
-                       return null;
-               }
-
-               protected string GetAddinTextFromUrl (XmlElement addin, string addinId, string fileId)
-               {
-                       if (addin == null)
-                               return "<html>Add-in not found: " + addinId + "</html>";
-                       
-                       StringBuilder sb = new StringBuilder ("<html>");
-                       sb.Append ("<h1>").Append (addin.GetAttribute ("name")).Append ("</h1>");
-                       XmlElement docs = (XmlElement) addin.SelectSingleNode ("Description");
-                       if (docs != null)
-                               sb.Append (docs.InnerText);
-
-                       sb.Append ("<p><table border=\"1\" cellpadding=\"4\" cellspacing=\"0\">");
-                       sb.AppendFormat ("<tr><td><b>Id</b></td><td>{0}</td></tr>", addin.GetAttribute ("addinId"));
-                       sb.AppendFormat ("<tr><td><b>Namespace</b></td><td>{0}</td></tr>", addin.GetAttribute ("namespace"));
-                       sb.AppendFormat ("<tr><td><b>Version</b></td><td>{0}</td></tr>", addin.GetAttribute ("version"));
-                       sb.Append ("</table></p>");
-                       sb.Append ("<p><b>Extension Points</b>:</p>");
-                       sb.Append ("<ul>");
-                       
-                       foreach (XmlElement ep in addin.SelectNodes ("ExtensionPoint")) {
-                               sb.AppendFormat ("<li><a href=\"extension-point:{0}#{1}#{2}\">{3}</li>", fileId, addinId, ep.GetAttribute ("path"), ep.GetAttribute ("name"));
-                       }
-                       sb.Append ("</ul>");
-                       
-                       sb.Append ("</html>");
-                       return sb.ToString ();
-               }
-               
-               protected string GetExtensionTextFromUrl (XmlElement addin, string addinId, string fileId, string path)
-               {
-                       if (addin == null)
-                               return "<html>Add-in not found: " + addinId + "</html>";
-                       
-                       XmlElement ext = (XmlElement) addin.SelectSingleNode ("ExtensionPoint[@path='" + path + "']");
-                       if (ext == null)
-                               return "<html>Extension point not found: " + path + "</html>";
-                       
-                       StringBuilder sb = new StringBuilder ("<html>");
-                       sb.Append ("<h1>").Append (ext.GetAttribute ("name")).Append ("</h1>");
-
-                       path = path.Replace ("/", " <b>/</b> ");
-                       sb.Append ("<p><b>Path</b>: ").Append (path).Append ("</p>");
-                       XmlElement desc = (XmlElement) ext.SelectSingleNode ("Description");
-                       if (desc != null)
-                               sb.Append (desc.InnerText);
-
-                       sb.Append ("<p><b>Extension Nodes</b>:</p>");
-                       sb.Append ("<table border=\"1\" cellpadding=\"4\" cellspacing=\"0\">");
-                       
-                       foreach (XmlElement en in ext.SelectNodes ("ExtensionNode")) {
-                               string nid = en.GetAttribute ("id");
-                               string nname = en.GetAttribute ("name"); 
-                               string sdesc = "";
-                               desc = (XmlElement) en.SelectSingleNode ("Description");
-                               if (desc != null)
-                                       sdesc = desc.InnerText;
-                               
-                               sb.AppendFormat ("<tr><td><a href=\"extension-node:{0}#{1}#{2}\">{3}</td><td>{4}</td></tr>", fileId, addinId, nid, nname, sdesc);
-                       }
-                       sb.Append ("</table>");
-                       
-                       sb.Append ("</html>");
-                       return sb.ToString ();
-               }
-               
-               protected string GetExtensionNodeTextFromUrl (XmlElement addin, string addinId, string fileId, string nodeId)
-               {
-                       if (addin == null)
-                               return "<html>Add-in not found: " + addinId + "</html>";
-                       
-                       XmlElement node = (XmlElement) addin.SelectSingleNode ("ExtensionNodeType[@id='" + nodeId + "']");
-                       if (node == null)
-                               return "<html>Extension point not found: " + nodeId + "</html>";
-                       
-                       StringBuilder sb = new StringBuilder ("<html>");
-                       sb.Append ("<h1>").Append (node.GetAttribute ("name")).Append ("</h1>");
-                       XmlElement desc = (XmlElement) node.SelectSingleNode ("Description");
-                       if (desc != null)
-                               sb.Append (desc.InnerText);
-
-                       sb.Append ("<p><b>Attributes</b>:</p>");
-                       sb.Append ("<table border=\"1\" cellpadding=\"4\" cellspacing=\"0\"><tr>");
-                       sb.Append ("<td><b>Name</b></td>");
-                       sb.Append ("<td><b>Type</b></td>");
-                       sb.Append ("<td><b>Required</b></td>");
-                       sb.Append ("<td><b>Localizable</b></td>");
-                       sb.Append ("<td><b>Description</b></td>");
-                       sb.Append ("<tr>");
-                       sb.Append ("<td>id</td>");
-                       sb.Append ("<td>System.String</td>");
-                       sb.Append ("<td></td>");
-                       sb.Append ("<td></td>");
-                       sb.Append ("<td>Identifier of the node.</td>");
-                       sb.Append ("</tr>");
-                       
-                       foreach (XmlElement at in node.SelectNodes ("Attributes/Attribute")) {
-                               sb.Append ("<tr>");
-                               sb.AppendFormat ("<td>{0}</td>", at.GetAttribute ("name"));
-                               sb.AppendFormat ("<td>{0}</td>", at.GetAttribute ("type"));
-                               if (at.GetAttribute ("required") == "True")
-                                       sb.Append ("<td>Yes</td>");
-                               else
-                                       sb.Append ("<td></td>");
-                               if (at.GetAttribute ("localizable") == "True")
-                                       sb.Append ("<td>Yes</td>");
-                               else
-                                       sb.Append ("<td></td>");
-                               string sdesc = "";
-                               desc = (XmlElement) at.SelectSingleNode ("Description");
-                               if (desc != null)
-                                       sdesc = desc.InnerText;
-                               
-                               sb.AppendFormat ("<td>{0}</td>", sdesc);
-                               sb.Append ("</tr>");
-                       }
-                       sb.Append ("</table>");
-
-                       XmlNodeList children = node.SelectNodes ("ChildNodes/ExtensionNode");
-                       if (children.Count > 0) {
-                               sb.Append ("<p><b>Child Nodes</b>:</p>");
-                               sb.Append ("<table border=\"1\" cellpadding=\"4\" cellspacing=\"0\">");
-                               
-                               foreach (XmlElement en in children) {
-                                       string nid = en.GetAttribute ("id");
-                                       string nname = en.GetAttribute ("name"); 
-                                       string sdesc = "";
-                                       desc = (XmlElement) en.SelectSingleNode ("Description");
-                                       if (desc != null)
-                                               sdesc = desc.InnerText;
-                                       
-                                       sb.AppendFormat ("<tr><td><a href=\"extension-node:{0}#{1}#{2}\">{3}</td><td>{4}</td></tr>", fileId, addinId, nid, nname, sdesc);
-                               }
-                               sb.Append ("</table>");
-                       }
-                       
-                       sb.Append ("</html>");
-                       return sb.ToString ();
-               }
-       }
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/generators/html/Ecma2Html.cs b/mcs/tools/monkeydoc/Monkeydoc/generators/html/Ecma2Html.cs
deleted file mode 100644 (file)
index ed329e3..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-using System;
-using System.IO;
-using System.Text;
-using System.Linq;
-using System.Xml;
-using System.Xml.Xsl;
-using System.Xml.XPath;
-using System.Collections.Generic;
-
-using Mono.Documentation;
-using BF = System.Reflection.BindingFlags;
-
-namespace MonkeyDoc.Generators.Html
-{
-       public class Ecma2Html : IHtmlExporter
-       {
-               static string css_ecma;
-               static string js;
-               static XslCompiledTransform ecma_transform;
-               readonly ExtensionObject ExtObject = new ExtensionObject ();
-
-               public Ecma2Html ()
-               {
-               }
-
-               public string CssCode {
-                       get {
-                               if (css_ecma != null)
-                                       return css_ecma;
-                               var assembly = typeof(Ecma2Html).Assembly;
-                               Stream str_css = assembly.GetManifestResourceStream ("mono-ecma.css");
-                               css_ecma = (new StreamReader (str_css)).ReadToEnd();
-                               return css_ecma;
-                       }
-               }
-
-               public string JsCode {
-                       get {
-                               if (js != null)
-                                       return js;
-                               var assembly = typeof(Ecma2Html).Assembly;
-                               Stream str_js = assembly.GetManifestResourceStream ("helper.js");
-                               js = (new StreamReader (str_js)).ReadToEnd();
-                               return js;
-                       }
-               }
-               
-               public string Htmlize (XmlReader ecma_xml, Dictionary<string, string> extraArgs)
-               {
-                       var args = new XsltArgumentList ();
-                       args.AddExtensionObject("monodoc:///extensions", ExtObject);
-                       foreach (var kvp in extraArgs)
-                               args.AddParam (kvp.Key, string.Empty, kvp.Value);
-
-                       return Htmlize(ecma_xml, args);
-               }
-
-               public string Htmlize (XmlReader ecma_xml, XsltArgumentList args)
-               {
-                       EnsureTransform ();
-               
-                       var output = new StringBuilder ();
-                       ecma_transform.Transform (ecma_xml, 
-                                                 args, 
-                                                 XmlWriter.Create (output, ecma_transform.OutputSettings),
-                                                 CreateDocumentResolver ());
-                       return output.ToString ();
-               }
-               
-               protected virtual XmlResolver CreateDocumentResolver ()
-               {
-                       // results in using XmlUrlResolver
-                       return null;
-               }
-
-               public string Export (Stream stream, Dictionary<string, string> extraArgs)
-               {
-                       return Htmlize (XmlReader.Create (stream), extraArgs);
-               }
-
-               public string Export (string input, Dictionary<string, string> extraArgs)
-               {
-                       return Htmlize (XmlReader.Create (new StringReader (input)), extraArgs);
-               }
-               
-               static void EnsureTransform ()
-               {
-                       if (ecma_transform == null) {
-                               ecma_transform = new XslCompiledTransform ();
-                               var assembly = System.Reflection.Assembly.GetCallingAssembly ();
-                       
-                               Stream stream = assembly.GetManifestResourceStream ("mono-ecma-css.xsl");
-                               XmlReader xml_reader = new XmlTextReader (stream);
-                               XmlResolver r = new ManifestResourceResolver (".");
-                               ecma_transform.Load (xml_reader, XsltSettings.TrustedXslt, r);                  
-                       }
-               }
-
-               public class ExtensionObject
-               {
-                       bool quiet = true;
-
-                       public string Colorize(string code, string lang)
-                       {
-                               return Mono.Utilities.Colorizer.Colorize(code,lang);
-                       }
-
-                       // Used by stylesheet to nicely reformat the <see cref=> tags. 
-                       public string MakeNiceSignature(string sig, string contexttype)
-                       {
-                               if (sig.Length < 3)
-                                       return sig;
-                               if (sig[1] != ':')
-                                       return sig;
-
-                               char s = sig[0];
-                               sig = sig.Substring(2);
-                       
-                               switch (s) {
-                               case 'N': return sig;
-                               case 'T': return ShortTypeName (sig, contexttype);
-
-                               case 'C': case 'M': case 'P': case 'F': case 'E':
-                                       string type, mem, arg;
-                                       
-                                       // Get arguments
-                                       int paren;
-                                       if (s == 'C' || s == 'M')
-                                               paren = sig.IndexOf("(");
-                                       else if (s == 'P')
-                                               paren = sig.IndexOf("[");
-                                       else
-                                               paren = 0;
-                                       
-                                       if (paren > 0 && paren < sig.Length-1) {
-                                               string[] args = sig.Substring(paren+1, sig.Length-paren-2).Split(',');                                          
-                                               for (int i = 0; i < args.Length; i++)
-                                                       args[i] = ShortTypeName(args[i], contexttype);
-                                               arg = "(" + String.Join(", ", args) + ")";
-                                               sig = sig.Substring(0, paren); 
-                                       } else {
-                                               arg = string.Empty;
-                                       }
-
-                                       // Get type and member names
-                                       int dot = sig.LastIndexOf(".");
-                                       if (s == 'C' || dot <= 0 || dot == sig.Length-1) {
-                                               mem = string.Empty;
-                                               type = sig;
-                                       } else {
-                                               type = sig.Substring(0, dot);
-                                               mem = sig.Substring(dot);
-                                       }
-                                               
-                                       type = ShortTypeName(type, contexttype);
-                                       
-                                       return type + mem + arg;
-
-                               default:
-                                       return sig;
-                               }
-                       }
-
-                       static string ShortTypeName(string name, string contexttype)
-                       {
-                               int dot = contexttype.LastIndexOf(".");
-                               if (dot < 0) return name;
-                               string contextns = contexttype.Substring(0, dot+1);
-
-                               if (name == contexttype)
-                                       return name.Substring(dot+1);
-                       
-                               if (name.StartsWith(contextns))
-                                       return name.Substring(contextns.Length);
-                       
-                               return name.Replace("+", ".");
-                       }
-
-                       string MonoImpInfo(string assemblyname, string typename, string membername, string arglist, bool strlong)
-                       {
-                               if (quiet)
-                                       return string.Empty;
-                               
-                               var a = new List<string> ();
-                               if (!string.IsNullOrEmpty (arglist)) a.Add (arglist);
-                               return MonoImpInfo(assemblyname, typename, membername, a, strlong);
-                       }
-
-                       string MonoImpInfo(string assemblyname, string typename, string membername, XPathNodeIterator itr, bool strlong)
-                       {
-                               if (quiet)
-                                       return string.Empty;
-                               
-                               var rgs = itr.Cast<XPathNavigator> ().Select (nav => nav.Value).ToList ();
-                       
-                               return MonoImpInfo (assemblyname, typename, membername, rgs, strlong);
-                       }
-               
-                       string MonoImpInfo(string assemblyname, string typename, string membername, List<string> arglist, bool strlong)
-                       {
-                               try {
-                                       System.Reflection.Assembly assembly = null;
-                               
-                                       try {
-                                               assembly = System.Reflection.Assembly.LoadWithPartialName(assemblyname);
-                                       } catch (Exception) {
-                                               // nothing.
-                                       }
-                               
-                                       if (assembly == null) {
-                                               /*if (strlong) return "The assembly " + assemblyname + " is not available to MonoDoc.";
-                                                 else return string.Empty;*/
-                                               return string.Empty; // silently ignore
-                                       }
-
-                                       Type t = assembly.GetType(typename, false);
-                                       if (t == null) {
-                                               if (strlong)
-                                                       return typename + " has not been implemented.";
-                                               else
-                                                       return "Not implemented.";
-                                       }
-
-                                       // The following code is flakey and fails to find existing members
-                                       return string.Empty;
-                               } catch (Exception) {
-                                       return string.Empty;
-                               }
-                       }
-               
-                       string MonoImpInfo(System.Reflection.MemberInfo mi, string itemtype, bool strlong)
-                       {
-                               if (quiet)
-                                       return string.Empty;
-                               
-                               string s = string.Empty;
-
-                               object[] atts = mi.GetCustomAttributes(true);
-                               int todoctr = 0;
-                               foreach (object att in atts) if (att.GetType().Name == "MonoTODOAttribute") todoctr++;
-
-                               if (todoctr > 0) {
-                                       if (strlong)
-                                               s = "This " + itemtype + " is marked as being unfinished.<BR/>\n";
-                                       else 
-                                               s = "Unfinished.";
-                               }
-
-                               return s;
-                       }
-
-                       public string MonoImpInfo(string assemblyname, string typename, bool strlong)
-                       {
-                               if (quiet)
-                                       return string.Empty;
-                               
-                               try {
-                                       if (assemblyname == string.Empty)
-                                               return string.Empty;
-
-                                       var assembly = System.Reflection.Assembly.LoadWithPartialName(assemblyname);
-                                       if (assembly == null)
-                                               return string.Empty;
-
-                                       Type t = assembly.GetType(typename, false);
-                                       if (t == null) {
-                                               if (strlong)
-                                                       return typename + " has not been implemented.";
-                                               else
-                                                       return "Not implemented.";
-                                       }
-
-                                       string s = MonoImpInfo(t, "type", strlong);
-
-                                       if (strlong) {
-                                               var mis = t.GetMembers (BF.Static | BF.Instance | BF.Public | BF.NonPublic);
-
-                                               // Scan members for MonoTODO attributes
-                                               int mctr = 0;
-                                               foreach (var mi in mis) {
-                                                       string mii = MonoImpInfo(mi, null, false);
-                                                       if (mii != string.Empty) mctr++; 
-                                               }
-                                               if (mctr > 0) {
-                                                       s += "This type has " + mctr + " members that are marked as unfinished.<BR/>";
-                                               }
-                                       }
-
-                                       return s;
-
-                               } catch (Exception) {
-                                       return string.Empty;
-                               }                       
-                       }
-
-                       public bool MonoEditing ()
-                       {
-                               return false;
-                       }
-               
-                       public bool IsToBeAdded(string text)
-                       {
-                               return text.StartsWith ("To be added");
-                       }
-               }
-       }
-}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/Monkeydoc/generators/html/Ecmaspec2Html.cs b/mcs/tools/monkeydoc/Monkeydoc/generators/html/Ecmaspec2Html.cs
deleted file mode 100644 (file)
index 95f4064..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-using System;
-using System.IO;
-using System.Xml;
-using System.Xml.Xsl;
-using System.Xml.XPath;
-using System.Collections.Generic;
-
-namespace MonkeyDoc.Generators.Html
-{
-       public class Ecmaspec2Html : IHtmlExporter
-       {
-               static string css_ecmaspec;
-               static XslTransform ecma_transform;
-               static XsltArgumentList args = new XsltArgumentList();
-
-               public string CssCode {
-                       get {
-                               if (css_ecmaspec != null)
-                                       return css_ecmaspec;
-                               System.Reflection.Assembly assembly = System.Reflection.Assembly.GetCallingAssembly ();
-                               Stream str_css = assembly.GetManifestResourceStream ("ecmaspec.css");
-                               css_ecmaspec = (new StreamReader (str_css)).ReadToEnd ();
-                               return css_ecmaspec;
-                       }
-               }
-
-               class ExtObj
-               {
-                       public string Colorize (string code, string lang)
-                       {
-                               return Mono.Utilities.Colorizer.Colorize (code, lang);
-                       }
-               }
-
-               public string Export (Stream stream, Dictionary<string, string> extraArgs)
-               {
-                       return Htmlize (new XPathDocument (stream));
-               }
-
-               public string Export (string input, Dictionary<string, string> extraArgs)
-               {
-                       return Htmlize (new XPathDocument (new StringReader (input)));
-               }
-
-               static string Htmlize (XPathDocument ecma_xml)
-               {
-                       if (ecma_transform == null){
-                               ecma_transform = new XslTransform ();
-                               System.Reflection.Assembly assembly = System.Reflection.Assembly.GetCallingAssembly ();
-                               Stream stream;
-                               stream = assembly.GetManifestResourceStream ("ecmaspec-html-css.xsl");
-
-                               XmlReader xml_reader = new XmlTextReader (stream);
-                               ecma_transform.Load (xml_reader, null, null);
-                               args.AddExtensionObject ("monodoc:///extensions", new ExtObj ()); 
-                       }
-               
-                       if (ecma_xml == null) return "";
-
-                       StringWriter output = new StringWriter ();
-                       ecma_transform.Transform (ecma_xml, args, output, null);
-               
-                       return output.ToString ();
-               }
-       }
-}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/Monkeydoc/generators/html/Error2Html.cs b/mcs/tools/monkeydoc/Monkeydoc/generators/html/Error2Html.cs
deleted file mode 100644 (file)
index 167d1f5..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-using System;
-using System.IO;
-using System.Linq;
-using System.Xml;
-using System.Xml.XPath;
-using System.Collections.Generic;
-
-namespace MonkeyDoc.Generators.Html
-{
-       public class Error2Html : IHtmlExporter
-       {
-               public string Export (string input, Dictionary<string, string> extraArgs)
-               {
-                       return Htmlize (new XPathDocument (new StringReader (input)));
-               }
-
-               public string Export (Stream input, Dictionary<string, string> extraArgs)
-               {
-                       return Htmlize (new XPathDocument (input));
-               }
-
-               public string CssCode {
-                       get {
-                               return @"
-                                        #error_ref { 
-                                           background: #debcb0; 
-                                           border: 2px solid #782609; 
-                                        }
-                                        div.summary {
-                                                font-size: 110%;
-                                                font-weight: bolder;
-                                        }
-                                        div.details {
-                                                font-size: 110%;
-                                                font-weight: bolder;
-                                        }
-                                        div.code_example {
-                                               background: #f5f5dd;
-                                               border: 1px solid black;
-                                               padding-left: 1em;
-                                               padding-bottom: 1em;
-                                               margin-top: 1em;
-                                               white-space: pre;
-                                               margin-bottom: 1em;
-                                        }
-                                        div.code_ex_title {
-                                               position: relative;
-                                               top: -1em;
-                                               left: 30%;
-                                               background: #cdcd82;
-                                               border: 1px solid black;
-                                               color: black;
-                                               font-size: 65%;
-                                               text-transform: uppercase;
-                                               width: 40%;
-                                               padding: 0.3em;
-                                               text-align: center;
-                                        }";
-                       }
-               }
-
-               public string Htmlize (IXPathNavigable doc)
-               {
-                       var navigator = doc.CreateNavigator ();
-                       var errorName = navigator.SelectSingleNode ("//ErrorDocumentation/ErrorName");
-                       var details = navigator.SelectSingleNode ("//ErrorDocumentation/Details");
-
-                       StringWriter sw = new StringWriter ();
-                       XmlWriter w = new XmlTextWriter (sw);
-                       
-                       WriteElementWithClass (w, "div", "header");
-                       w.WriteAttributeString ("id", "error_ref");
-                       WriteElementWithClass (w, "div", "subtitle", "Compiler Error Reference");
-                       WriteElementWithClass (w, "div", "title", "Error " + (errorName == null ? string.Empty : errorName.Value));
-                       w.WriteEndElement ();
-
-                       if (details != null) {
-                               WriteElementWithClass (w, "div", "summary", "Summary");
-
-                               var summary = details.SelectSingleNode ("/Summary");
-                               w.WriteValue (summary == null ? string.Empty : summary.Value);
-                               
-                               WriteElementWithClass (w, "div", "details", "Details");
-                               var de = details.SelectSingleNode ("/Details");
-                               w.WriteValue (de == null ? string.Empty : de.Value);
-                       }
-                       
-                       foreach (XPathNavigator xmp in navigator.Select ("//ErrorDocumentation/Examples/string")) {
-                               WriteElementWithClass (w, "div", "code_example");
-                               WriteElementWithClass (w, "div", "code_ex_title", "Example");
-                               w.WriteRaw (Mono.Utilities.Colorizer.Colorize (xmp.Value, "c#"));;
-                               w.WriteEndElement ();
-                       }
-                       
-                       w.Close ();
-                       
-                       return sw.ToString ();
-               }
-
-               void WriteElementWithClass (XmlWriter w, string element, string cls, string content = null)
-               {
-                       w.WriteStartElement (element);
-                       w.WriteAttributeString ("class", cls);
-                       if (!string.IsNullOrEmpty (content)) {
-                               w.WriteValue (content);
-                               w.WriteEndElement ();
-                       }
-               }
-       }
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/generators/html/Idem.cs b/mcs/tools/monkeydoc/Monkeydoc/generators/html/Idem.cs
deleted file mode 100644 (file)
index 0a58b21..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-using System;
-using System.IO;
-using System.Text;
-using System.Collections.Generic;
-
-using MonkeyDoc;
-using MonkeyDoc.Generators;
-
-namespace MonkeyDoc.Generators.Html
-{
-       // Input is expected to be already HTML so just return it
-       public class Idem : IHtmlExporter
-       {
-               public string CssCode {
-                       get {
-                               return string.Empty;
-                       }
-               }
-
-               public string Export (Stream input, Dictionary<string, string> extraArgs)
-               {
-                       if (input == null)
-                               return null;
-                       return new StreamReader (input).ReadToEnd ();
-               }
-
-               public string Export (string input, Dictionary<string, string> extraArgs)
-               {
-                       if (string.IsNullOrEmpty (input))
-                               return null;
-                       return input;
-               }
-       }
-}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/Monkeydoc/generators/html/Man2Html.cs b/mcs/tools/monkeydoc/Monkeydoc/generators/html/Man2Html.cs
deleted file mode 100644 (file)
index 68ed5ed..0000000
+++ /dev/null
@@ -1,316 +0,0 @@
-using System;
-using System.IO;
-using System.Text;
-using System.Collections.Generic;
-
-using MonkeyDoc;
-using MonkeyDoc.Generators;
-
-namespace MonkeyDoc.Generators.Html
-{
-       public class Man2Html : IHtmlExporter
-       {
-               public string CssCode {
-                       get {
-                               return string.Empty;
-                       }
-               }
-
-               public string Export (Stream input, Dictionary<string, string> extraArgs)
-               {
-                       if (input == null)
-                               return null;
-                       return GetTextFromReader (new StreamReader (input));
-               }
-
-               public string Export (string input, Dictionary<string, string> extraArgs)
-               {
-                       if (string.IsNullOrEmpty (input))
-                               return null;
-                       return GetTextFromReader (new StringReader (input));
-               }
-
-               public static string GetTextFromReader (TextReader file)
-               {
-                       string line;
-                       StateInfo s = new StateInfo ();
-
-                       while ((line = file.ReadLine ()) != null)
-                               ProcessLine (line, s);
-
-                       return s.output.ToString ();
-               }
-
-               enum ListState {
-                       None,
-                       Start,
-                       Title,
-               }
-
-               class StateInfo {
-                       public ListState ls;
-                       public Stack<string> tags = new Stack<string> ();
-                       public StringBuilder output = new StringBuilder ();
-               }
-
-               static void ProcessLine (string line, StateInfo s)
-               {
-                       string[] parts = SplitLine (line);
-                       switch (parts [0]) {
-                       case ".\\\"": // comments
-                       case ".de":   // define macro
-                       case ".if":   // if
-                       case ".ne":   // ???
-                       case "..":    // end macro
-                               // ignore
-                               break;
-                       case ".I":
-                               s.output.Append ("<i>");
-                               Translate (parts, 1, s.output);
-                               s.output.Append ("</i>");
-                               break;
-                       case ".B":
-                               s.output.Append ("<b>");
-                               Translate (parts, 1, s.output);
-                               s.output.Append ("</b>");
-                               break;
-                       case ".br":
-                               Translate (parts, 1, s.output);
-                               s.output.Append ("<br />");
-                               break;
-                       case ".nf":
-                               Expect (s, "</p>");
-                               s.output.Append ("<pre>\n");
-                               s.tags.Push ("</pre>");
-                               break;
-                       case ".fi":
-                               Expect (s, "</pre>");
-                               break;
-                       case ".PP":
-                               Expect (s, "</p>", "</dd>", "</dl>");
-                               goto case ".Sp";
-                       case ".Sp":
-                               Expect (s, "</p>");
-                               s.output.Append ("<p>");
-                               Translate (parts, 1, s.output);
-                               s.tags.Push ("</p>");
-                               break;
-                       case ".RS":
-                               Expect (s, "</p>");
-                               s.output.Append ("<blockquote>");
-                               s.tags.Push ("</blockquote>");
-                               break;
-                       case ".RE":
-                               ClearUntil (s, "</blockquote>");
-                               break;
-                       case ".SH":
-                               ClearAll (s);
-                               s.output.Append ("<h2>");
-                               Translate (parts, 1, s.output);
-                               s.output.Append ("</h2>")
-                                       .Append ("<blockquote>");
-                               s.tags.Push ("</blockquote>");
-                               break;
-                       case ".SS":
-                               s.output.Append ("<h3>");
-                               Translate (parts, 1, s.output);
-                               s.output.Append ("</h3>");
-                               break;
-                       case ".TH": {
-                               ClearAll (s);
-                               string name = "", extra = "";
-                               if (parts.Length >= 4 && parts [2].Trim ().Length == 0) {
-                                       name = parts [1] + "(" + parts [3] + ")";
-                                       if (parts.Length > 4) {
-                                               int start = 4;
-                                               if (parts [start].Trim ().Length == 0)
-                                                       ++start;
-                                               extra = string.Join ("", parts, start, parts.Length-start);
-                                       }
-                               }
-                               else
-                                       name = string.Join ("", parts, 1, parts.Length-1);
-                               s.output.Append ("<table width=\"100%\" bgcolor=\"#b0c4da\">" + 
-                                                "<tr colspan=\"2\"><td>Manual Pages</td></tr>\n" +
-                                                "<tr><td><h3>");
-                               Translate (name, s.output);
-                               s.output.Append ("</h3></td><td align=\"right\">");
-                               Translate (extra, s.output);
-                               s.output.Append ("</td></tr></table>");
-                               break;
-                       }
-                       case ".TP":
-                               Expect (s, "</p>");
-                               if (s.tags.Count > 0 && s.tags.Peek ().ToString () != "</dd>") {
-                                       s.output.Append ("<dl>");
-                                       s.tags.Push ("</dl>");
-                               }
-                               else
-                                       Expect (s, "</dd>");
-                               s.output.Append ("<dt>");
-                               s.tags.Push ("</dt>");
-                               s.ls = ListState.Start;
-                               break;
-                       default:
-                               Translate (line, s.output);
-                               break;
-                       }
-                       if (s.ls == ListState.Start)
-                               s.ls = ListState.Title;
-                       else if (s.ls == ListState.Title) {
-                               Expect (s, "</dt>");
-                               s.output.Append ("<dd>");
-                               s.tags.Push ("</dd>");
-                               s.ls = ListState.None;
-                       }
-                       s.output.Append ("\n");
-               }
-
-               static string[] SplitLine (string line)
-               {
-                       if (line.Length > 1 && line [0] != '.')
-                               return new string[]{null, line};
-
-                       int i;
-                       for (i = 0; i < line.Length; ++i) {
-                               if (char.IsWhiteSpace (line, i))
-                                       break;
-                       }
-
-                       if (i == line.Length)
-                               return new string[]{line};
-
-                       var pieces = new List<string> ();
-                       pieces.Add (line.Substring (0, i));
-                       bool inQuotes = false;
-                       bool prevWs   = true;
-                       ++i;
-                       int start = i;
-                       for ( ; i < line.Length; ++i) {
-                               char c = line [i];
-                               if (inQuotes) {
-                                       if (c == '"') {
-                                               Add (pieces, line, start, i);
-                                               start = i+1;
-                                               inQuotes = false;
-                                       }
-                               }
-                               else {
-                                       if (prevWs && c == '"') {
-                                               Add (pieces, line, start, i);
-                                               start = i+1;
-                                               inQuotes = true;
-                                       }
-                                       else if (char.IsWhiteSpace (c)) {
-                                               if (!prevWs) {
-                                                       Add (pieces, line, start, i);
-                                                       start = i;
-                                               }
-                                               prevWs = true;
-                                       }
-                                       else {
-                                               if (prevWs) {
-                                                       Add (pieces, line, start, i);
-                                                       start = i;
-                                               }
-                                               prevWs = false;
-                                       }
-                               }
-                       }
-                       if (start > 0 && start != line.Length)
-                               pieces.Add (line.Substring (start, line.Length-start));
-                       return pieces.ToArray ();
-               }
-
-               static void Add (List<string> pieces, string line, int start, int end)
-               {
-                       if (start == end)
-                               return;
-                       pieces.Add (line.Substring (start, end-start));
-               }
-
-               static void Expect (StateInfo s, params string[] expected)
-               {
-                       string e;
-                       while (s.tags.Count > 0 && 
-                              Array.IndexOf (expected, (e = s.tags.Peek ().ToString ())) >= 0) {
-                               s.output.Append (s.tags.Pop ().ToString ());
-                       }
-               }
-
-               static void ClearUntil (StateInfo s, string required)
-               {
-                       string e;
-                       while (s.tags.Count > 0 && 
-                              (e = s.tags.Peek ().ToString ()) != required) {
-                               s.output.Append (s.tags.Pop ().ToString ());
-                       }
-                       if (e == required)
-                               s.output.Append (s.tags.Pop ().ToString ());
-               }
-
-               static void ClearAll (StateInfo s)
-               {
-                       while (s.tags.Count > 0)
-                               s.output.Append (s.tags.Pop ().ToString ());
-               }
-
-               static void Translate (string[] lines, int startIndex, StringBuilder output)
-               {
-                       if (lines.Length <= startIndex)
-                               return;
-                       do {
-                               Translate (lines [startIndex++], output);
-                               if (startIndex == lines.Length)
-                                       break;
-                       } while (startIndex < lines.Length);
-               }
-
-               static void Translate (string line, StringBuilder output)
-               {
-                       string span = null;
-                       int start = output.Length;
-                       for (int i = 0; i < line.Length; ++i) {
-                               switch (line [i]) {
-                               case '\\': {
-                                       if ((i+2) < line.Length && line [i+1] == 'f') {
-                                               if (line [i+2] == 'I') {
-                                                       output.Append ("<i>");
-                                                       span = "</i>";
-                                               }
-                                               else if (line [i+2] == 'B') {
-                                                       output.Append ("<b>");
-                                                       span = "</b>";
-                                               }
-                                               else if (line [i+2] == 'R' || line [i+2] == 'P') {
-                                                       output.Append (span);
-                                               }
-                                               else
-                                                       goto default;
-                                               i += 2;
-                                       }
-                                       else if ((i+1) < line.Length) {
-                                               output.Append (line [i+1]);
-                                               ++i;
-                                       }
-                                       else
-                                               goto default;
-                                       break;
-                               }
-                               case '<':
-                                       output.Append ("&lt;");
-                                       break;
-                               case '>':
-                                       output.Append ("&gt;");
-                                       break;
-                               case '&':
-                                       output.Append ("&amp;");
-                                       break;
-                               default:
-                                       output.Append (line [i]);
-                                       break;
-                               }
-                       }
-               }
-       }
-}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/Monkeydoc/generators/html/MonoBook2Html.cs b/mcs/tools/monkeydoc/Monkeydoc/generators/html/MonoBook2Html.cs
deleted file mode 100644 (file)
index 89a531c..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-using System;
-using System.IO;
-using System.Text;
-using System.Xml;
-using System.Collections.Generic;
-
-using MonkeyDoc;
-using MonkeyDoc.Generators;
-
-namespace MonkeyDoc.Generators.Html
-{
-       // Input is expected to be already HTML so just return it
-       public class MonoBook2Html : IHtmlExporter
-       {
-               public string CssCode {
-                       get {
-                               return @"   h3 { 
-       font-size: 18px;
-       padding-bottom: 4pt;
-       border-bottom: 2px solid #dddddd;
-   }
-       
-   .api {
-     border: 1px solid;
-     padding: 10pt;
-     margin: 10pt;
-   } 
-
-   .api-entry { 
-       border-bottom: none;
-       font-size: 18px;
-   }
-
-   .prototype {
-     border: 1px solid;
-     background-color: #f2f2f2;
-     padding: 5pt;
-     margin-top: 5pt;
-     margin-bottom: 5pt;  
-   } 
-
-   .header {
-     border: 1px solid !important;
-     padding: 0 0 5pt 5pt !important;
-     margin: 10pt !important;
-     white-space: pre !important;
-       font-family: monospace !important;
-     font-weight: normal !important;
-     font-size: 1em !important;
-   }
-    
-   .code {
-     border: 1px solid;
-     padding: 0 0 5pt 5pt;
-     margin: 10pt;
-     white-space: pre;
-       font-family: monospace;
-   }
-";
-                       }
-               }
-
-               public string Export (Stream input, Dictionary<string, string> extraArgs)
-               {
-                       if (input == null)
-                               return null;
-                       return FromXmlReader (XmlReader.Create (input));
-               }
-
-               public string Export (string input, Dictionary<string, string> extraArgs)
-               {
-                       if (string.IsNullOrEmpty (input))
-                               return null;
-                       return FromXmlReader (XmlReader.Create (new StringReader (input)));
-               }
-
-               public string FromXmlReader (XmlReader reader)
-               {
-                       if (!reader.ReadToDescendant ("head"))
-                               return null;
-                       if (!reader.ReadToNextSibling ("body"))
-                               return null;
-
-                       return reader.ReadInnerXml ();
-               }
-       }
-}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/Monkeydoc/generators/html/Toc2Html.cs b/mcs/tools/monkeydoc/Monkeydoc/generators/html/Toc2Html.cs
deleted file mode 100644 (file)
index eef17c2..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-using System;
-using System.IO;
-using System.Xml;
-using System.Xml.Xsl;
-using System.Xml.XPath;
-using System.Reflection;
-using System.Collections.Generic;
-
-namespace MonkeyDoc.Generators.Html
-{
-       public class Toc2Html : IHtmlExporter
-       {
-               XslTransform transform;
-
-               public Toc2Html ()
-               {
-                       transform = new XslTransform ();
-                       var assembly = Assembly.GetCallingAssembly ();
-                       var stream = assembly.GetManifestResourceStream ("toc-html.xsl");
-                       XmlReader xml_reader = new XmlTextReader (stream);
-                       transform.Load (xml_reader, null, null);
-               }
-
-               public string Export (Stream input, Dictionary<string, string> extraArgs)
-               {
-                       var output = new StringWriter ();
-                       transform.Transform (new XPathDocument (input), null, output, null);
-                       return output.ToString ();
-               }
-
-               public string Export (string input, Dictionary<string, string> extraArgs)
-               {
-                       var output = new StringWriter ();
-                       transform.Transform (new XPathDocument (new StringReader (input)), null, output, null);
-                       return output.ToString ();
-               }
-
-               public string CssCode {
-                       get {
-                               return string.Empty;
-                       }
-               }
-       }
-}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/Monkeydoc/index.cs b/mcs/tools/monkeydoc/Monkeydoc/index.cs
deleted file mode 100644 (file)
index b365b9e..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-//
-// index.cs: Handling of the index files
-//
-// Author:
-//   Miguel de Icaza (miguel@xamarin.com)
-//
-// (C) 2003 Ximian, Inc.
-// Copyright 2003-2011 Novell Inc
-// Copyright 2011 Xamarin Inc.
-//
-// Possible file format optimizations:
-//   * Do not use 4 bytes for each index entry, use 3 bytes
-//   * Find a way of compressing strings, there are plenty of duplicates
-//     Find common roots, and use an encoding that uses a root to compress data.
-//     "System", "System.Data", "System.Data class"
-//     0: PLAIN: "System"
-//     1: PLAIN: " class"
-//     2: LINK0 PLAIN ".DATA"
-//     3: LINK0 LINK1
-//     
-//     Maybe split everything at spaces and dots, and encode that:
-//     string-1-idx "System."
-//     string-1-idx "Data"
-//     2-items [ string-1-idx string-2-idx]
-//
-//     Other variations are possible;  Like Archive "System", "System." when we
-//     see "System.Data".
-//
-//
-
-using System;
-using System.IO;
-using System.Text;
-using System.Collections.Generic;
-
-namespace MonkeyDoc
-{
-       public class Topic
-       {
-               public readonly string Caption;
-               public readonly string SortKey;
-               public readonly string Url;
-
-               public Topic (string caption, string sort_key, string url)
-               {
-                       Caption = caption;
-                       SortKey = sort_key;
-                       Url = url;
-               }
-       }
-
-       public class IndexEntry
-       {
-               List<Topic> topics;
-
-               public int Position {
-                       get;
-                       private set;
-               }
-
-               public IList<Topic> Topics {
-                       get {
-                               return topics.AsReadOnly ();
-                       }
-               }
-
-               public int Count {
-                       get;
-                       private set;
-               }
-               
-               public void Add (Topic t)
-               {
-                       Count++;
-                       topics.Add (t);
-               }
-
-               public Topic this [int idx] {
-                       get {
-                               if (idx < 0 || idx > topics.Count)
-                                       throw new ArgumentOutOfRangeException ("idx");
-                               return topics[idx];
-                       }
-               }
-
-               //
-               // Constructor from a stream
-               //
-               public IndexEntry (FileStream fs, BinaryReader reader, int position)
-               {
-                       Count = reader.ReadInt32 ();
-                       int caption_offset = reader.ReadInt32 ();
-                       string caption;
-                       topics = new List<Topic> (Count);
-
-                       int [] offsets = new int [Count];
-                       for (int i = 0; i < Count; i++)
-                               offsets [i] = reader.ReadInt32 ();
-
-                       fs.Position = caption_offset;
-                       caption = reader.ReadString ();
-                       for (int i = 0; i < Count; i++){
-                               fs.Position = offsets [i];
-                               string url = reader.ReadString ();
-                               topics.Add (new Topic (caption, string.Empty, url));
-                       }
-               }
-
-               //
-               // Regular constructor
-       
-               public IndexEntry ()
-               {
-                       topics = new List<Topic> ();
-               }
-
-               public void WriteTopics (IndexMaker maker, Stream stream, BinaryWriter writer)
-               {
-                       //
-                       // Convention: entries with the same SortKey should have the same Caption
-                       //
-                       Position = (int) stream.Position;
-                       writer.Write (Count);
-
-                       if (Count == 0)
-                               return;
-
-                       writer.Write (maker.GetCode (topics[0].Caption));
-                       foreach (Topic t in topics)
-                               writer.Write (maker.GetCode (t.Url));
-               }
-       }
-
-       public class IndexMaker
-       {
-               Dictionary<string, IndexEntry> entries = new Dictionary<string, IndexEntry> ();
-               Dictionary<string, int> all_strings = new Dictionary<string, int> ();
-               int index_position;
-
-               void AddString (string str)
-               {
-                       if (!all_strings.ContainsKey (str))
-                               all_strings.Add (str, 0);
-               }
-
-               public void AddTopic (Topic topic)
-               {
-                       IndexEntry entry;
-                       if (!entries.TryGetValue (topic.SortKey, out entry)) {
-                               entry = new IndexEntry ();
-                               entries[topic.SortKey] = entry;
-                       }
-
-                       AddString (topic.SortKey);
-                       AddString (topic.Caption);
-                       AddString (topic.Url);
-                       entry.Add (topic);
-               }
-
-               public void Add (string caption, string sort_key, string url)
-               {
-                       Topic t = new Topic (caption, sort_key, url);
-                       AddTopic (t);
-               }
-       
-               void SaveStringTable (Stream stream, BinaryWriter writer)
-               {
-                       var keys = new List<string> (all_strings.Keys);
-                       foreach (string s in keys) {
-                               int pos = (int) stream.Position;
-                               writer.Write (s);
-                               all_strings [s] = pos;
-                       }
-               }
-
-               public int GetCode (string s)
-               {
-                       return all_strings [s];
-               }
-
-               void SaveTopics (Stream stream, BinaryWriter writer)
-               {
-                       //
-                       // Convention: entries with the same SortKey should have the same Caption
-                       //
-                       foreach (IndexEntry e in entries.Values)
-                               e.WriteTopics (this, stream, writer);
-               }
-
-               void SaveIndexEntries (Stream stream, BinaryWriter writer)
-               {
-                       index_position = (int) stream.Position;
-                       writer.Write (entries.Count);
-                       var keys = new List<string> (entries.Keys);
-                       keys.Sort (StringComparer.OrdinalIgnoreCase);
-               
-                       foreach (string s in keys){
-                               IndexEntry e = entries [s];
-                               writer.Write (e.Position);
-                       }
-               }
-
-               public void Save (string filename)
-               {
-                       Encoding utf8 = new UTF8Encoding (false, true);
-
-                       using (FileStream fs = File.OpenWrite (filename)){
-                               BinaryWriter writer = new BinaryWriter (fs, utf8);
-                               writer.Write (new byte [] { (byte) 'M', 
-                                                           (byte) 'o', (byte) 'i', 
-                                                           (byte) 'x'});
-
-                               // Leave room for pointer
-                               fs.Position = 8;
-
-                               SaveStringTable (fs, writer);
-                               SaveTopics (fs, writer);
-
-                               // index_position is set here
-                       
-                               SaveIndexEntries (fs, writer);
-
-                               fs.Position = 4;
-                               writer.Write (index_position);
-                       }
-               }
-       }
-
-       public interface IListModel
-       {
-               int Rows { get; }
-               string GetValue (int row);
-               string GetDescription (int row);
-       }
-
-       public class IndexReader : IListModel
-       {
-               Encoding utf8 = new UTF8Encoding (false, true);
-               FileStream fs;
-               BinaryReader reader;
-
-               // The offset of the table of entries
-               int table_offset;
-               int entries;
-
-               static public IndexReader Load (string filename)
-               {
-                       if (!File.Exists (filename))
-                               return null;
-
-                       try {
-                               return new IndexReader (filename);
-                       } catch {
-                               return null;
-                       }
-               }
-       
-               IndexReader (string filename)
-               {
-                       fs = File.OpenRead (filename);
-                       reader = new BinaryReader (fs, utf8);
-
-                       if (fs.ReadByte () != 'M' ||
-                           fs.ReadByte () != 'o' ||
-                           fs.ReadByte () != 'i' ||
-                           fs.ReadByte () != 'x'){
-                               throw new Exception ("Corrupt index");
-                       }
-
-                       // Seek to index_entries
-                       fs.Position = reader.ReadInt32 ();
-               
-                       entries = reader.ReadInt32 ();
-
-                       table_offset = (int) fs.Position;
-               }
-
-               public int Rows {
-                       get {
-                               return entries;
-                       }
-               }
-
-               public string GetValue (int row)
-               {
-                       fs.Position = row * 4 + table_offset;
-                       fs.Position = reader.ReadInt32 () + 4;
-                       int code = reader.ReadInt32 ();
-                       fs.Position = code;
-                       string caption = reader.ReadString ();
-
-                       return caption;
-               }
-
-               public string GetDescription (int row)
-               {
-                       return GetValue (row);
-               }
-       
-               public IndexEntry GetIndexEntry (int row)
-               {
-                       fs.Position = row * 4 + table_offset;
-                       int entry_offset = reader.ReadInt32 ();
-                       fs.Position = entry_offset;
-               
-                       return new IndexEntry (fs, reader, entry_offset);
-               }
-       }
-}
-
diff --git a/mcs/tools/monkeydoc/Monkeydoc/providers/EcmaDoc.cs b/mcs/tools/monkeydoc/Monkeydoc/providers/EcmaDoc.cs
deleted file mode 100644 (file)
index 1d3c9fb..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-using System;
-using System.Linq;
-using System.IO;
-using System.Text;
-using System.Xml;
-using System.Xml.Linq;
-using System.Collections.Generic;
-
-namespace MonkeyDoc.Providers
-{
-       // Common functionality between ecma-provider and ecmauncompiled-provider
-       internal class EcmaDoc
-       {
-               public static void PopulateTreeFromIndexFile (string indexFilePath,
-                                                             Tree tree,
-                                                             IDocStorage storage,
-                                                             Dictionary<string, XElement> nsSummaries,
-                                                             Func<XElement, string> indexGenerator = null)
-               {
-                       var root = tree.RootNode;
-                       int resID = 0;
-                       var asm = Path.GetDirectoryName (indexFilePath);
-
-                       storage = storage ?? new Storage.NullStorage ();
-                       // nsSummaries is allowed to be null if the user doesn't care about it
-                       nsSummaries = nsSummaries ?? new Dictionary<string, XElement> ();
-                       // default index generator uses a counter
-                       indexGenerator = indexGenerator ?? (_ => resID++.ToString ());
-
-                       using (var reader = XmlReader.Create (File.OpenRead (indexFilePath))) {
-                               reader.ReadToFollowing ("Types");
-                               var types = XElement.Load (reader.ReadSubtree ());
-
-                               foreach (var ns in types.Elements ("Namespace")) {
-                                       var nsName = (string)ns.Attribute ("Name");
-                                       nsName = !string.IsNullOrEmpty (nsName) ? nsName : "global";
-                                       var nsNode = root.GetOrCreateNode (nsName, "N:" + nsName);
-
-                                       XElement nsElements;
-                                       if (!nsSummaries.TryGetValue (nsName, out nsElements))
-                                               nsSummaries[nsName] = nsElements = new XElement ("elements",
-                                                                                                new XElement ("summary"),
-                                                                                                new XElement ("remarks"));
-
-                                       foreach (var type in ns.Elements ("Type")) {
-                                               // Add the XML file corresponding to the type to our storage
-                                               var id = indexGenerator (type);
-                                               string typeFilePath;
-                                               var typeDocument = EcmaDoc.LoadTypeDocument (asm, nsName, type.Attribute ("Name").Value, out typeFilePath);
-                                               if (typeDocument == null)
-                                                       continue;
-                                               using (var file = File.OpenRead (typeFilePath))
-                                                       storage.Store (id, file);
-                                               nsElements.Add (ExtractClassSummary (typeFilePath));
-
-                                               var typeCaption = EcmaDoc.GetTypeCaptionFromIndex (type);
-                                               var url = "ecma:" + id + '#' + typeCaption + '/';
-                                               typeCaption = EcmaDoc.GetTypeCaptionFromIndex (type, true);
-                                               var typeNode = nsNode.CreateNode (typeCaption, url);
-
-                                               // Add meta "Members" node
-                                               typeNode.CreateNode ("Members", "*");
-                                               var membersNode = typeDocument.Root.Element ("Members");
-                                               if (membersNode == null || !membersNode.Elements ().Any ())
-                                                       continue;
-                                               var members = membersNode
-                                                       .Elements ("Member")
-                                                       .ToLookup (EcmaDoc.GetMemberType);
-
-                                               foreach (var memberType in members) {
-                                                       // We pluralize the member type to get the caption and take the first letter as URL
-                                                       var node = typeNode.CreateNode (EcmaDoc.PluralizeMemberType (memberType.Key), memberType.Key[0].ToString ());
-                                                       var memberIndex = 0;
-
-                                                       var isCtors = memberType.Key[0] == 'C';
-
-                                                       // We do not escape much member name here
-                                                       foreach (var memberGroup in memberType.GroupBy (m => MakeMemberCaption (m, isCtors))) {
-                                                               if (memberGroup.Count () > 1) {
-                                                                       // Generate overload
-                                                                       var overloadCaption = MakeMemberCaption (memberGroup.First (), false);
-                                                                       var overloadNode = node.CreateNode (overloadCaption, overloadCaption);
-                                                                       foreach (var member in memberGroup)
-                                                                               overloadNode.CreateNode (MakeMemberCaption (member, true), (memberIndex++).ToString ());
-                                                                       overloadNode.Sort ();
-                                                               } else {
-                                                                       // We treat constructor differently by showing their argument list in all cases
-                                                                       node.CreateNode (MakeMemberCaption (memberGroup.First (), isCtors), (memberIndex++).ToString ());
-                                                               }
-                                                       }
-                                                       node.Sort ();
-                                               }
-                                       }
-
-                                       nsNode.Sort ();
-                               }
-                               root.Sort ();
-                       }
-               }
-
-               // Utility methods
-
-               public static XDocument LoadTypeDocument (string basePath, string nsName, string typeName)
-               {
-                       string dummy;
-                       return LoadTypeDocument (basePath, nsName, typeName, out dummy);
-               }
-
-               public static XDocument LoadTypeDocument (string basePath, string nsName, string typeName, out string finalPath)
-               {
-                       finalPath = Path.Combine (basePath, nsName, Path.ChangeExtension (typeName, ".xml"));
-                       if (!File.Exists (finalPath)) {
-                               Console.Error.WriteLine ("Warning: couldn't process type file `{0}' as it doesn't exist", finalPath);
-                               return null;
-                       }
-                       return XDocument.Load (finalPath);
-               }
-
-               public static string GetTypeCaptionFromIndex (XElement typeNodeFromIndex, bool full = false)
-               {
-                       var t = typeNodeFromIndex;
-                       var c = ((string)(t.Attribute ("DisplayName") ?? t.Attribute ("Name"))).Replace ('+', '.');
-                       if (full)
-                               c += " " + (string)t.Attribute ("Kind");
-                       return c;
-               }
-
-               public static string PluralizeMemberType (string memberType)
-               {
-                       switch (memberType) {
-                       case "Property":
-                               return "Properties";
-                       default:
-                               return memberType + "s";
-                       }
-               }
-
-               public static string GetMemberType (XElement m)
-               {
-                       return m.Attribute ("MemberName").Value.StartsWith ("op_") ? "Operator" : m.Element ("MemberType").Value;
-               }
-
-               public static string MakeMemberCaption (XElement member, bool withArguments)
-               {
-                       var caption = (string)member.Attribute ("MemberName");
-                       // Use type name instead of .ctor for cosmetic sake
-                       if (caption == ".ctor") {
-                               caption = (string)member.Ancestors ("Type").First ().Attribute ("Name");
-                               // If this is an inner type ctor, strip the parent type reference
-                               var plusIndex = caption.LastIndexOf ('+');
-                               if (plusIndex != -1)
-                                       caption = caption.Substring (plusIndex + 1);
-                       }
-                       if (caption.StartsWith ("op_")) {
-                               string sig;
-                               caption = MakeOperatorSignature (member, out sig);
-                               caption = withArguments ? sig : caption;
-                               return caption;
-                       }
-                       if (withArguments) {
-                               var args = member.Element ("Parameters");
-                               caption += '(';
-                               if (args != null && args.Elements ("Parameter").Any ()) {
-                                       caption += args.Elements ("Parameter")
-                                               .Select (p => (string)p.Attribute ("Type"))
-                                               .Aggregate ((p1, p2) => p1 + "," + p2);
-                               }
-                               caption += ')';
-                       }
-                       
-                       return caption;
-               }
-
-               internal static string MakeOperatorSignature (XElement member, out string memberSignature)
-               {
-                       string name = (string)member.Attribute ("MemberName");
-                       var nicename = name.Substring(3);
-                       memberSignature = null;
-
-                       switch (name) {
-                       // unary operators: no overloading possible     [ECMA-335 §10.3.1]
-                       case "op_UnaryPlus":                    // static     R operator+       (T)
-                       case "op_UnaryNegation":                // static     R operator-       (T)
-                       case "op_LogicalNot":                   // static     R operator!       (T)
-                       case "op_OnesComplement":               // static     R operator~       (T)
-                       case "op_Increment":                    // static     R operator++      (T)
-                       case "op_Decrement":                    // static     R operator--      (T)
-                       case "op_True":                         // static  bool operator true   (T)
-                       case "op_False":                        // static  bool operator false  (T)
-                       case "op_AddressOf":                    // static     R operator&       (T)
-                       case "op_PointerDereference":           // static     R operator*       (T)
-                               memberSignature = nicename;
-                               break;
-                       // conversion operators: overloading based on parameter and return type [ECMA-335 §10.3.3]
-                       case "op_Implicit":                    // static implicit operator R (T)
-                       case "op_Explicit":                    // static explicit operator R (T)
-                               nicename = name.EndsWith ("Implicit") ? "ImplicitConversion" : "ExplicitConversion";
-                               string arg = (string)member.Element ("Parameters").Element ("Parameter").Attribute ("Type");
-                               string ret = (string)member.Element ("ReturnValue").Element ("ReturnType");
-                               memberSignature = arg + " to " + ret;
-                               break;
-                       // binary operators: overloading is possible [ECMA-335 §10.3.2]
-                       default:
-                               memberSignature =
-                                       nicename + "("
-                                       + string.Join (",", member.Element ("Parameters").Elements ("Parameter").Select (p => (string)p.Attribute ("Type")))
-                                       + ")";
-                               break;
-                       }
-
-                       return nicename;
-               }
-
-               static XElement ExtractClassSummary (string typeFilePath)
-               {
-                       using (var reader = XmlReader.Create (typeFilePath)) {
-                               reader.ReadToFollowing ("Type");
-                               var name = reader.GetAttribute ("Name");
-                               var fullName = reader.GetAttribute ("FullName");
-                               reader.ReadToFollowing ("AssemblyName");
-                               var assemblyName = reader.ReadElementString ();
-                               reader.ReadToFollowing ("summary");
-                               var summary = reader.ReadInnerXml ();
-                               reader.ReadToFollowing ("remarks");
-                               var remarks = reader.ReadInnerXml ();
-
-                               return new XElement ("class",
-                                                    new XAttribute ("name", name ?? string.Empty),
-                                                    new XAttribute ("fullname", fullName ?? string.Empty),
-                                                    new XAttribute ("assembly", assemblyName ?? string.Empty),
-                                                    new XElement ("summary", new XCData (summary)),
-                                                    new XElement ("remarks", new XCData (remarks)));
-                       }
-               }
-       }
-}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/Monkeydoc/providers/addins-provider.cs b/mcs/tools/monkeydoc/Monkeydoc/providers/addins-provider.cs
deleted file mode 100644 (file)
index 3768717..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-// addins-provider.cs
-//
-// A provider to display Mono.Addins extension models
-//
-// Author:
-//   Lluis Sanchez Gual <lluis@novell.com>
-//
-// Copyright (c) 2007 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-//
-
-using System;
-using System.Linq;
-using System.Diagnostics;
-using System.Text;
-using System.IO;
-using System.Xml;
-using System.Collections.Generic;
-
-namespace MonkeyDoc.Providers
-{
-       public class AddinsProvider : Provider
-       {
-               string file;
-               
-               public AddinsProvider (string xmlModelFile)
-               {
-                       file = xmlModelFile;
-                       
-                       if (!File.Exists (file))
-                               throw new FileNotFoundException (String.Format ("The file `{0}' does not exist", file));
-               }
-
-               public override void PopulateTree (Tree tree)
-               {
-                       string fileId = Path.GetFileNameWithoutExtension (file);
-                       using (var f = File.OpenRead (file))
-                               tree.HelpSource.Storage.Store (fileId, f);
-
-                       XmlDocument doc = new XmlDocument ();
-                       doc.Load (file);
-                       
-                       foreach (XmlElement addin in doc.SelectNodes ("Addins/Addin")) {
-
-                               string addinId = addin.GetAttribute ("fullId");
-                               Node newNode = tree.RootNode.CreateNode (addin.GetAttribute ("name"), "addin:" + fileId + "#" + addinId);
-
-                               foreach (XmlElement node in addin.SelectNodes ("ExtensionPoint")) {
-                                       string target = "extension-point:" + fileId + "#" + addinId + "#" + node.GetAttribute ("path");
-                                       Node newExt = newNode.CreateNode (node.GetAttribute ("name"), target);
-                       
-                                       foreach (XmlElement en in node.SelectNodes ("ExtensionNode")) {
-                                               string nid = en.GetAttribute ("id");
-                                               string nname = en.GetAttribute ("name");
-                                               newExt.CreateNode (nname, "extension-node:" + fileId + "#" + addinId + "#" + nid);
-                                       }
-                               }
-                       }
-               }
-
-               public override void CloseTree (HelpSource hs, Tree tree)
-               {
-               }
-       }
-
-       public class AddinsHelpSource : HelpSource
-       {
-               public AddinsHelpSource (string base_file, bool create) : base (base_file, create) 
-               {
-               }
-               
-               internal protected const string AddinPrefix = "addin:";
-               internal protected const string ExtensionPrefix = "extension-point:";
-               internal protected const string ExtensionNodePrefix = "extension-node:";
-
-               public override bool CanHandleUrl (string url)
-               {
-                       return url.StartsWith (AddinPrefix, StringComparison.OrdinalIgnoreCase)
-                               || url.StartsWith (ExtensionPrefix, StringComparison.OrdinalIgnoreCase)
-                               || url.StartsWith (ExtensionNodePrefix, StringComparison.OrdinalIgnoreCase);
-               }
-
-               protected override string UriPrefix {
-                       get {
-                               return AddinPrefix;
-                       }
-               }
-               
-               public override DocumentType GetDocumentTypeForId (string id, out Dictionary<string, string> extraArgs)
-               {
-                       extraArgs = new Dictionary<string, string> ();
-                       var idParts = id.Split ('#');
-                       extraArgs["FileID"] = idParts[0];
-                       extraArgs["AddinID"] = idParts[1];
-                       extraArgs["NodeID"] = idParts[2];
-
-                       return DocumentType.AddinXml;
-               }
-
-               public override Node MatchNode (string url)
-               {
-                       var prefix = new[] { AddinPrefix, ExtensionPrefix, ExtensionNodePrefix }.First (p => url.StartsWith (p, StringComparison.OrdinalIgnoreCase));
-                       return base.MatchNode (prefix != null ? url.Substring (prefix.Length) : url);
-               }
-
-               public override Stream GetHelpStream (string id)
-               {
-                       var idParts = id.Split ('#');
-                       return base.GetHelpStream (idParts[0]);
-               }
-
-               public override Stream GetCachedHelpStream (string id)
-               {
-                       var idParts = id.Split ('#');
-                       return base.GetHelpStream (idParts[0]);
-               }
-       }
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/providers/ecma-provider.cs b/mcs/tools/monkeydoc/Monkeydoc/providers/ecma-provider.cs
deleted file mode 100644 (file)
index a30872b..0000000
+++ /dev/null
@@ -1,1070 +0,0 @@
-//
-// The ecmaspec provider is for ECMA specifications
-//
-// Authors:
-//     John Luke (jluke@cfl.rr.com)
-//     Ben Maurer (bmaurer@users.sourceforge.net)
-//
-// Use like this:
-//   mono assembler.exe --ecmaspec DIRECTORY --out name
-//
-
-using System;
-using System.Linq;
-using System.IO;
-using System.Text;
-using System.Xml;
-using System.Xml.Linq;
-using System.Collections.Generic;
-
-using Lucene.Net.Index;
-using Lucene.Net.Documents;
-
-using MonkeyDoc.Ecma;
-using Mono.Utilities;
-
-namespace MonkeyDoc.Providers
-{
-       public enum EcmaNodeType {
-               Invalid,
-               Namespace,
-               Type,
-               Member,
-               Meta, // A node that's here to serve as a header for other node
-       }
-
-       public class EcmaProvider : Provider
-       {
-               HashSet<string> directories = new HashSet<string> ();
-
-               public EcmaProvider ()
-               {
-               }
-
-               public EcmaProvider (string baseDir)
-               {
-                       AddDirectory (baseDir);
-               }
-
-               public void AddDirectory (string directory)
-               {
-                       if (string.IsNullOrEmpty (directory))
-                               throw new ArgumentNullException ("directory");
-
-                       directories.Add (directory);
-               }
-
-               public override void PopulateTree (Tree tree)
-               {
-                       var storage = tree.HelpSource.Storage;
-                       var nsSummaries = new Dictionary<string, XElement> ();
-                       int resID = 0;
-
-                       foreach (var asm in directories) {
-                               var indexFilePath = Path.Combine (asm, "index.xml");
-                               if (!File.Exists (indexFilePath)) {
-                                       Console.Error.WriteLine ("Warning: couldn't process directory `{0}' as it has no index.xml file", asm);
-                                       continue;
-                               }
-
-                               EcmaDoc.PopulateTreeFromIndexFile (indexFilePath, tree, storage, nsSummaries, _ => resID++.ToString ());
-                       }
-
-                       foreach (var summary in nsSummaries)
-                               storage.Store ("xml.summary." + summary.Key, summary.Value.ToString ());
-
-                       var masterSummary = new XElement ("elements",
-                                                         directories
-                                                         .SelectMany (d => Directory.EnumerateFiles (d, "ns-*.xml"))
-                                                         .Select (ExtractNamespaceSummary));
-                       storage.Store ("mastersummary.xml", masterSummary.ToString ());
-               }
-
-               XElement ExtractNamespaceSummary (string nsFile)
-               {
-                       using (var reader = XmlReader.Create (nsFile)) {
-                               reader.ReadToFollowing ("Namespace");
-                               var name = reader.GetAttribute ("Name");
-                               reader.ReadToFollowing ("summary");
-                               var summary = reader.ReadInnerXml ();
-                               reader.ReadToFollowing ("remarks");
-                               var remarks = reader.ReadInnerXml ();
-
-                               return new XElement ("namespace",
-                                                    new XAttribute ("ns", name ?? string.Empty),
-                                                    new XElement ("summary", new XCData (summary)),
-                                                    new XElement ("remarks", new XCData (remarks)));
-                       }
-               }
-
-               public override void CloseTree (HelpSource hs, Tree tree)
-               {
-                       AddImages (hs);
-                       AddExtensionMethods (hs);
-               }
-
-               void AddEcmaXml (HelpSource hs)
-               {
-                       var xmls = directories
-                               .SelectMany (Directory.EnumerateDirectories) // Assemblies
-                               .SelectMany (Directory.EnumerateDirectories) // Namespaces
-                               .SelectMany (Directory.EnumerateFiles)
-                               .Where (f => f.EndsWith (".xml")); // Type XML files
-
-                       int resID = 0;
-                       foreach (var xml in xmls)
-                               using (var file = File.OpenRead (xml))
-                                       hs.Storage.Store ((resID++).ToString (), file);
-               }
-
-               void AddImages (HelpSource hs)
-               {
-                       var imgs = directories
-                               .SelectMany (Directory.EnumerateDirectories)
-                               .Select (d => Path.Combine (d, "_images"))
-                               .Where (Directory.Exists)
-                               .SelectMany (Directory.EnumerateFiles);
-
-                       foreach (var img in imgs)
-                               using (var file = File.OpenRead (img))
-                                       hs.Storage.Store (Path.GetFileName (img), file);
-               }
-
-               void AddExtensionMethods (HelpSource hs)
-               {
-                       var extensionMethods = directories
-                               .SelectMany (Directory.EnumerateDirectories)
-                               .Select (d => Path.Combine (d, "index.xml"))
-                               .Where (File.Exists)
-                               .Select (f => {
-                                       using (var file = File.OpenRead (f)) {
-                                               var reader = XmlReader.Create (file);
-                                               reader.ReadToFollowing ("ExtensionMethods");
-                                               return reader.ReadInnerXml ();
-                                       }
-                           })
-                           .DefaultIfEmpty (string.Empty);
-
-                       hs.Storage.Store ("ExtensionMethods.xml",
-                                         "<ExtensionMethods>" + extensionMethods.Aggregate (string.Concat) + "</ExtensionMethods>");
-               }
-
-               IEnumerable<string> GetEcmaXmls ()
-               {
-                       return directories
-                               .SelectMany (Directory.EnumerateDirectories) // Assemblies
-                               .SelectMany (Directory.EnumerateDirectories) // Namespaces
-                               .SelectMany (Directory.EnumerateFiles)
-                               .Where (f => f.EndsWith (".xml")); // Type XML files
-               }
-       }
-
-       public class EcmaHelpSource : HelpSource
-       {
-               const string EcmaPrefix = "ecma:";
-               EcmaUrlParser parser = new EcmaUrlParser ();
-               LRUCache<string, Node> cache = new LRUCache<string, Node> (4);
-
-               public EcmaHelpSource (string base_file, bool create) : base (base_file, create)
-               {
-               }
-
-               protected EcmaHelpSource () : base ()
-               {
-               }
-
-               protected override string UriPrefix {
-                       get {
-                               return EcmaPrefix;
-                       }
-               }
-
-               public override bool CanHandleUrl (string url)
-               {
-                       if (url.Length > 2 && url[1] == ':') {
-                               switch (url[0]) {
-                               case 'T':
-                               case 'M':
-                               case 'C':
-                               case 'P':
-                               case 'E':
-                               case 'F':
-                               case 'N':
-                               case 'O':
-                                       return true;
-                               }
-                       }
-                       return base.CanHandleUrl (url);
-               }
-
-               // Clean the extra paramers in the id
-               public override Stream GetHelpStream (string id)
-               {
-                       var idParts = id.Split ('?');
-                       return base.GetHelpStream (idParts[0]);
-               }
-
-               public override Stream GetCachedHelpStream (string id)
-               {
-                       var idParts = id.Split ('?');
-                       return base.GetCachedHelpStream (idParts[0]);
-               }
-
-               public override DocumentType GetDocumentTypeForId (string id, out Dictionary<string, string> extraParams)
-               {
-                       extraParams = null;
-                       int interMark = id.LastIndexOf ('?');
-                       if (interMark != -1)
-                               extraParams = id.Substring (interMark)
-                                       .Split ('&')
-                                       .Select (nvp => {
-                                               var eqIdx = nvp.IndexOf ('=');
-                                               return new { Key = nvp.Substring (0, eqIdx < 0 ? nvp.Length : eqIdx), Value = nvp.Substring (eqIdx + 1) };
-                                       })
-                                       .ToDictionary (kvp => kvp.Key, kvp => kvp.Value );
-                       return DocumentType.EcmaXml;
-               }
-
-               public override string GetPublicUrl (Node node)
-               {
-                       string url = string.Empty;
-                       var type = GetNodeType (node);
-                       //Console.WriteLine ("GetPublicUrl {0} : {1} [{2}]", node.Element, node.Caption, type.ToString ());
-                       switch (type) {
-                       case EcmaNodeType.Namespace:
-                               return node.Element; // A namespace node has already a well formated internal url
-                       case EcmaNodeType.Type:
-                               return MakeTypeNodeUrl (node);
-                       case EcmaNodeType.Meta:
-                               return MakeTypeNodeUrl (GetNodeTypeParent (node)) + GenerateMetaSuffix (node);
-                       case EcmaNodeType.Member:
-                               var typeChar = GetNodeMemberTypeChar (node);
-                               var parentNode = GetNodeTypeParent (node);
-                               var typeNode = MakeTypeNodeUrl (parentNode).Substring (2);
-                               return typeChar + ":" + typeNode + MakeMemberNodeUrl (typeChar, node);
-                       default:
-                               return null;
-                       }
-               }
-
-               string MakeTypeNodeUrl (Node node)
-               {
-                       // A Type node has a Element property of the form: 'ecma:{number}#{typename}/'
-                       var hashIndex = node.Element.IndexOf ('#');
-                       var typeName = node.Element.Substring (hashIndex + 1, node.Element.Length - hashIndex - 2);
-                       return "T:" + node.Parent.Caption + '.' + typeName.Replace ('.', '+');
-               }
-
-               string MakeMemberNodeUrl (char typeChar, Node node)
-               {
-                       // We clean inner type ctor name which may contain the outer type name
-                       var caption = node.Caption;
-
-                       // Sanitize constructor caption of inner types
-                       if (typeChar == 'C') {
-                               int lastDot = -1;
-                               for (int i = 0; i < caption.Length && caption[i] != '('; i++)
-                                       lastDot = caption[i] == '.' ? i : lastDot;
-                               return lastDot == -1 ? '.' + caption : caption.Substring (lastDot);
-                       }
-
-                       /* We handle type conversion operator by checking if the name contains " to "
-                        * (as in 'foo to bar') and we generate a corresponding conversion signature
-                        */
-                       if (typeChar == 'O' && caption.IndexOf (" to ") != -1) {
-                               var parts = caption.Split (' ');
-                               return "." + node.Parent.Caption + "(" + parts[0] + ", " + parts[2] + ")";
-                       }
-
-                       /* The goal here is to treat method which are explicit interface definition
-                        * such as 'void IDisposable.Dispose ()' for which the caption is a dot
-                        * expression thus colliding with the ecma parser.
-                        * If the first non-alpha character in the caption is a dot then we have an
-                        * explicit member implementation (we assume the interface has namespace)
-                        */
-                       var firstNonAlpha = caption.FirstOrDefault (c => !char.IsLetterOrDigit (c));
-                       if (firstNonAlpha == '.')
-                               return "$" + caption;
-
-                       return "." + caption;
-               }
-
-               EcmaNodeType GetNodeType (Node node)
-               {
-                       // We guess the node type by checking the depth level it's at in the tree
-                       int level = GetNodeLevel (node);
-                       switch (level) {
-                       case 0:
-                               return EcmaNodeType.Namespace;
-                       case 1:
-                               return EcmaNodeType.Type;
-                       case 2:
-                               return EcmaNodeType.Meta;
-                       case 3: // Here it's either a member or, in case of overload, a meta
-                               return node.IsLeaf ? EcmaNodeType.Member : EcmaNodeType.Meta;
-                       case 4: // At this level, everything is necessarily a member
-                               return EcmaNodeType.Member;
-                       default:
-                               return EcmaNodeType.Invalid;
-                       }
-               }
-
-               int GetNodeLevel (Node node)
-               {
-                       int i = 0;
-                       for (; !node.Element.StartsWith ("root:/", StringComparison.OrdinalIgnoreCase); i++) {
-                               //Console.WriteLine ("\tLevel {0} : {1} {2}", i, node.Element, node.Caption);
-                               node = node.Parent;
-                       }
-                       return i - 1;
-               }
-
-               char GetNodeMemberTypeChar (Node node)
-               {
-                       int level = GetNodeLevel (node);
-                       // We try to reach the member group node depending on node nested level
-                       switch (level) {
-                       case 2:
-                               return node.Element[0];
-                       case 3:
-                               return node.Parent.Element[0];
-                       case 4:
-                               return node.Parent.Parent.Element[0];
-                       default:
-                               throw new ArgumentException ("node", "Couldn't determine member type of node `" + node.Caption + "'");
-                       }
-               }
-
-               Node GetNodeTypeParent (Node node)
-               {
-                       // Type nodes are always at level 2 so we just need to get there
-                       while (node != null && node.Parent != null && !node.Parent.Parent.Element.StartsWith ("root:/", StringComparison.OrdinalIgnoreCase))
-                               node = node.Parent;
-                       return node;
-               }
-
-               string GenerateMetaSuffix (Node node)
-               {
-                       string suffix = string.Empty;
-                       // A meta node has always a type element to begin with
-                       while (GetNodeType (node) != EcmaNodeType.Type) {
-                               suffix = '/' + node.Element + suffix;
-                               node = node.Parent;
-                       }
-                       return suffix;
-               }
-
-               public override string GetInternalIdForUrl (string url, out Node node)
-               {
-                       var id = string.Empty;
-                       node = null;
-
-                       if (!url.StartsWith (UriPrefix, StringComparison.OrdinalIgnoreCase)) {
-                               node = MatchNode (url);
-                               if (node == null)
-                                       return null;
-                               id = node.GetInternalUrl ();
-                       }
-
-                       string hash;
-                       id = GetInternalIdForInternalUrl (id, out hash);
-
-                       return id + GetArgs (hash, node);
-               }
-
-               public string GetInternalIdForInternalUrl (string internalUrl, out string hash)
-               {
-                       var id = internalUrl;
-                       if (id.StartsWith (UriPrefix, StringComparison.OrdinalIgnoreCase))
-                               id = id.Substring (UriPrefix.Length);
-                       else if (id.StartsWith ("N:", StringComparison.OrdinalIgnoreCase))
-                               id = "xml.summary." + id.Substring ("N:".Length);
-
-                       var hashIndex = id.IndexOf ('#');
-                       hash = string.Empty;
-                       if (hashIndex != -1) {
-                               hash = id.Substring (hashIndex + 1);
-                               id = id.Substring (0, hashIndex);
-                       }
-
-                       return id;
-               }
-
-               public override Node MatchNode (string url)
-               {
-                       Node node = null;
-                       if ((node = cache.Get (url)) == null) {
-                               node = InternalMatchNode (url);
-                               if (node != null)
-                                       cache.Put (url, node);
-                       }
-                       return node;
-               }
-
-               public Node InternalMatchNode (string url)
-               {
-                       Node result = null;
-                       EcmaDesc desc;
-                       if (!parser.TryParse (url, out desc))
-                               return null;
-
-                       // Namespace search
-                       Node currentNode = Tree.RootNode;
-                       Node searchNode = new Node () { Caption = desc.Namespace };
-                       int index = currentNode.Nodes.BinarySearch (searchNode, EcmaGenericNodeComparer.Instance);
-                       if (index >= 0)
-                               result = currentNode.Nodes[index];
-                       if (desc.DescKind == EcmaDesc.Kind.Namespace || index < 0)
-                               return result;
-
-                       // Type search
-                       currentNode = result;
-                       result = null;
-                       searchNode.Caption = desc.ToCompleteTypeName ();
-                       index = currentNode.Nodes.BinarySearch (searchNode, EcmaTypeNodeComparer.Instance);
-                       if (index >= 0)
-                               result = currentNode.Nodes[index];
-                       if ((desc.DescKind == EcmaDesc.Kind.Type && !desc.IsEtc) || index < 0)
-                               return result;
-
-                       // Member selection
-                       currentNode = result;
-                       result = null;
-                       var caption = desc.IsEtc ? EtcKindToCaption (desc.Etc) : MemberKindToCaption (desc.DescKind);
-                       currentNode = FindNodeForCaption (currentNode.Nodes, caption);
-                       if (currentNode == null 
-                           || (desc.IsEtc && desc.DescKind == EcmaDesc.Kind.Type && string.IsNullOrEmpty (desc.EtcFilter)))
-                               return currentNode;
-
-                       // Member search
-                       result = null;
-                       var format = desc.DescKind == EcmaDesc.Kind.Constructor ? EcmaDesc.Format.WithArgs : EcmaDesc.Format.WithoutArgs;
-                       searchNode.Caption = desc.ToCompleteMemberName (format);
-                       index = currentNode.Nodes.BinarySearch (searchNode, EcmaGenericNodeComparer.Instance);
-                       if (index < 0)
-                               return null;
-                       result = currentNode.Nodes[index];
-                       if (result.Nodes.Count == 0 || desc.IsEtc)
-                               return result;
-
-                       // Overloads search
-                       currentNode = result;
-                       searchNode.Caption = desc.ToCompleteMemberName (EcmaDesc.Format.WithArgs);
-                       index = currentNode.Nodes.BinarySearch (searchNode, EcmaGenericNodeComparer.Instance);
-                       if (index < 0)
-                               return result;
-                       result = result.Nodes[index];
-                       
-                       return result;
-               }
-
-               // This comparer returns the answer straight from caption comparison
-               class EcmaGenericNodeComparer : IComparer<Node>
-               {
-                       public static readonly EcmaGenericNodeComparer Instance = new EcmaGenericNodeComparer ();
-
-                       public int Compare (Node n1, Node n2)
-                       {
-                               return string.Compare (n1.Caption, n2.Caption, StringComparison.Ordinal);
-                       }
-               }
-
-               // This comparer take into account the space in the caption
-               class EcmaTypeNodeComparer : IComparer<Node>
-               {
-                       public static readonly EcmaTypeNodeComparer Instance = new EcmaTypeNodeComparer ();
-
-                       public int Compare (Node n1, Node n2)
-                       {
-                               int length1 = CaptionLength (n1.Caption);
-                               int length2 = CaptionLength (n2.Caption);
-
-                               return string.Compare (n1.Caption, 0, n2.Caption, 0, Math.Max (length1, length2), StringComparison.Ordinal);
-                       }
-
-                       int CaptionLength (string caption)
-                       {
-                               var length = caption.LastIndexOf (' ');
-                               return length == -1 ? caption.Length : length;
-                       }
-               }
-
-               string EtcKindToCaption (char etc)
-               {
-                       switch (etc) {
-                       case 'M':
-                               return "Methods";
-                       case 'P':
-                               return "Properties";
-                       case 'C':
-                               return "Constructors";
-                       case 'F':
-                               return "Fields";
-                       case 'E':
-                               return "Events";
-                       case 'O':
-                               return "Operators";
-                       case '*':
-                               return "Members";
-                       default:
-                               return null;
-                       }
-               }
-
-               string MemberKindToCaption (EcmaDesc.Kind kind)
-               {
-                       switch (kind) {
-                       case EcmaDesc.Kind.Method:
-                               return "Methods";
-                       case EcmaDesc.Kind.Property:
-                               return "Properties";
-                       case EcmaDesc.Kind.Constructor:
-                               return "Constructors";
-                       case EcmaDesc.Kind.Field:
-                               return "Fields";
-                       case EcmaDesc.Kind.Event:
-                               return "Events";
-                       case EcmaDesc.Kind.Operator:
-                               return "Operators";
-                       default:
-                               return null;
-                       }
-               }
-
-               Node FindNodeForCaption (List<Node> nodes, string caption)
-               {
-                       foreach (var node in nodes)
-                               if (node.Caption.Equals (caption, StringComparison.OrdinalIgnoreCase))
-                                       return node;
-                       return null;
-               }
-
-               string GetArgs (string hash, Node node)
-               {
-                       var args = new Dictionary<string, string> ();
-                       
-                       args["source-id"] = SourceID.ToString ();
-                       
-                       if (node != null) {
-                               var nodeType = GetNodeType (node);
-                               switch (nodeType) {
-                               case EcmaNodeType.Namespace:
-                                       args["show"] = "namespace";
-                                       args["namespace"] = node.Element.Substring ("N:".Length);
-                                       break;
-                               case EcmaNodeType.Type:
-                                       args["show"] = "typeoverview";
-                                       break;
-                               case EcmaNodeType.Member:
-                               case EcmaNodeType.Meta:
-                                       switch (GetNodeMemberTypeChar (node)){
-                                       case 'C':
-                                               args["membertype"] = "Constructor";
-                                               break;
-                                       case 'M':
-                                               args["membertype"] = "Method";
-                                               break;
-                                       case 'P':
-                                               args["membertype"] = "Property";
-                                               break;
-                                       case 'F':
-                                               args["membertype"] = "Field";
-                                               break;
-                                       case 'E':
-                                               args["membertype"] = "Event";
-                                               break;
-                                       case 'O':
-                                               args["membertype"] = "Operator";
-                                               break;
-                                       case 'X':
-                                               args["membertype"] = "ExtensionMethod";
-                                               break;
-                                       case '*':
-                                               args["membertype"] = "All";
-                                               break;
-                                       }
-
-                                       if (nodeType == EcmaNodeType.Meta) {
-                                               args["show"] = "members";
-                                               args["index"] = "all";
-                                       } else {
-                                               args["show"] = "member";
-                                               args["index"] = node.Element;
-                                       }
-                                       break;
-                               }
-                       }
-
-                       if (!string.IsNullOrEmpty (hash))
-                               args["hash"] = hash;
-
-                       return "?" + string.Join ("&", args.Select (kvp => kvp.Key == kvp.Value ? kvp.Key : kvp.Key + '=' + kvp.Value));
-               }
-
-               public override void PopulateIndex (IndexMaker index_maker)
-               {
-                       foreach (Node ns_node in Tree.RootNode.Nodes){
-                               foreach (Node type_node in ns_node.Nodes){
-                                       string typename = type_node.Caption.Substring (0, type_node.Caption.IndexOf (' '));
-                                       string full = ns_node.Caption + "." + typename;
-
-                                       string doc_tag = GetKindFromCaption (type_node.Caption);
-                                       string url = type_node.PublicUrl;
-
-                                       //
-                                       // Add MonoMac/MonoTouch [Export] attributes, those live only in classes
-                                       //
-                                       XDocument type_doc = null;
-                                       ILookup<string, XElement> prematchedMembers = null;
-                                       bool hasExports = doc_tag == "Class" && (ns_node.Caption.StartsWith ("MonoTouch") || ns_node.Caption.StartsWith ("MonoMac"));
-                                       if (hasExports) {
-                                               try {
-                                                       string rest, hash;
-                                                       var id = GetInternalIdForInternalUrl (type_node.GetInternalUrl (), out hash);
-                                                       type_doc = XDocument.Load (GetHelpStream (id));
-                                                       prematchedMembers = type_doc.Root.Element ("Members").Elements ("Member").ToLookup (n => (string)n.Attribute ("MemberName"), n => n);
-                                               } catch (Exception e) {
-                                                       Console.WriteLine ("Problem processing {0} for MonoTouch/MonoMac exports\n\n{0}", e);
-                                                       hasExports = false;
-                                               }
-                                       }
-
-                                       if (doc_tag == "Class" || doc_tag == "Structure" || doc_tag == "Interface"){
-                                               index_maker.Add (type_node.Caption, typename, url);
-                                               index_maker.Add (full + " " + doc_tag, full, url);
-
-                                               foreach (Node c in type_node.Nodes){
-                                                       switch (c.Caption){
-                                                       case "Constructors":
-                                                               index_maker.Add ("  constructors", typename+"0", url + "/C");
-                                                               break;
-                                                       case "Fields":
-                                                               index_maker.Add ("  fields", typename+"1", url + "/F");
-                                                               break;
-                                                       case "Events":
-                                                               index_maker.Add ("  events", typename+"2", url + "/E");
-                                                               break;
-                                                       case "Properties":
-                                                               index_maker.Add ("  properties", typename+"3", url + "/P");
-                                                               break;
-                                                       case "Methods":
-                                                               index_maker.Add ("  methods", typename+"4", url + "/M");
-                                                               break;
-                                                       case "Operators":
-                                                               index_maker.Add ("  operators", typename+"5", url + "/O");
-                                                               break;
-                                                       }
-                                               }
-
-                                               //
-                                               // Now repeat, but use a different sort key, to make sure we come after
-                                               // the summary data above, start the counter at 6
-                                               //
-                                               string keybase = typename + "6.";
-
-                                               foreach (Node c in type_node.Nodes){
-                                                       var type = c.Caption[0];
-
-                                                       foreach (Node nc in c.Nodes) {
-                                                               string res = nc.Caption;
-                                                               string nurl = nc.PublicUrl;
-
-                                                               // Process exports
-                                                               if (hasExports && (type == 'C' || type == 'M' || type == 'P')) {
-                                                                       try {
-                                                                               var member = GetMemberFromCaption (type_doc, type == 'C' ? ".ctor" : res, false, prematchedMembers);
-                                                                               var exports = member.Descendants ("AttributeName").Where (a => a.Value.Contains ("Foundation.Export"));
-                                                                               foreach (var exportNode in exports) {
-                                                                                       var parts = exportNode.Value.Split ('"');
-                                                                                       if (parts.Length != 3) {
-                                                                                               Console.WriteLine ("Export attribute not found or not usable in {0}", exportNode);
-                                                                                       } else {
-                                                                                               var export = parts[1];
-                                                                                               index_maker.Add (export + " selector", export, nurl);
-                                                                                       }
-                                                                               }
-                                                                       } catch (Exception e) {
-                                                                               Console.WriteLine ("Problem processing {0}/{1} for MonoTouch/MonoMac exports\n\n{2}", nurl, res, e);
-                                                                       }
-                                                               }
-
-                                                               switch (type){
-                                                               case 'C':
-                                                                       break;
-                                                               case 'F':
-                                                                       index_maker.Add (String.Format ("{0}.{1} field", typename, res),
-                                                                                        keybase + res, nurl);
-                                                                       index_maker.Add (String.Format ("{0} field", res), res, nurl);
-                                                                       break;
-                                                               case 'E':
-                                                                       index_maker.Add (String.Format ("{0}.{1} event", typename, res),
-                                                                                        keybase + res, nurl);
-                                                                       index_maker.Add (String.Format ("{0} event", res), res, nurl);
-                                                                       break;
-                                                               case 'P':
-                                                                       index_maker.Add (String.Format ("{0}.{1} property", typename, res),
-                                                                                        keybase + res, nurl);
-                                                                       index_maker.Add (String.Format ("{0} property", res), res, nurl);
-                                                                       break;
-                                                               case 'M':
-                                                                       index_maker.Add (String.Format ("{0}.{1} method", typename, res),
-                                                                                        keybase + res, nurl);
-                                                                       index_maker.Add (String.Format ("{0} method", res), res, nurl);
-                                                                       break;
-                                                               case 'O':
-                                                                       index_maker.Add (String.Format ("{0}.{1} operator", typename, res),
-                                                                                        keybase + res, nurl);
-                                                                       break;
-                                                               }
-                                                       }
-                                               }
-                                       } else if (doc_tag == "Enumeration"){
-                                               //
-                                               // Enumerations: add the enumeration values
-                                               //
-                                               index_maker.Add (type_node.Caption, typename, url);
-                                               index_maker.Add (full + " " + doc_tag, full, url);
-
-                                               // Now, pull the values.
-                                               string rest, hash;
-                                               var id = GetInternalIdForInternalUrl (type_node.GetInternalUrl (), out hash);
-                                               var xdoc = XDocument.Load (GetHelpStream (id));
-                                               if (xdoc == null)
-                                                       continue;
-
-                                               var members = xdoc.Root.Element ("Members").Elements ("Members");
-                                               if (members == null)
-                                                       continue;
-
-                                               foreach (var member_node in members){
-                                                       string enum_value = member_node.Attribute ("MemberName").Value;
-                                                       string caption = enum_value + " value";
-                                                       index_maker.Add (caption, caption, url);
-                                               }
-                                       } else if (doc_tag == "Delegate"){
-                                               index_maker.Add (type_node.Caption, typename, url);
-                                               index_maker.Add (full + " " + doc_tag, full, url);
-                                       }
-                               }
-                       }
-               }
-
-
-               public override void PopulateSearchableIndex (IndexWriter writer)
-               {
-                       StringBuilder text = new StringBuilder ();
-                       SearchableDocument searchDoc = new SearchableDocument ();
-
-                       foreach (Node ns_node in Tree.RootNode.Nodes) {
-                               foreach (Node type_node in ns_node.Nodes) {
-                                       string typename = type_node.Caption.Substring (0, type_node.Caption.IndexOf (' '));
-                                       string full = ns_node.Caption + "." + typename;
-                                       string url = type_node.PublicUrl;
-                                       string doc_tag = GetKindFromCaption (type_node.Caption);
-                                       string rest, hash;
-                                       var id = GetInternalIdForInternalUrl (type_node.GetInternalUrl (), out hash);
-                                       var xdoc = XDocument.Load (GetHelpStream (id));
-                                       if (xdoc == null)
-                                               continue;
-                                       if (string.IsNullOrEmpty (doc_tag)) {
-                                               Console.WriteLine (type_node.Caption);
-                                               continue;
-                                       }       
-
-                                       // For classes, structures or interfaces add a doc for the overview and
-                                       // add a doc for every constructor, method, event, ...
-                                       // doc_tag == "Class" || doc_tag == "Structure" || doc_tag == "Interface"
-                                       if (doc_tag[0] == 'C' || doc_tag[0] == 'S' || doc_tag[0] == 'I') {
-                                               // Adds a doc for every overview of every type
-                                               SearchableDocument doc = searchDoc.Reset ();
-                                               doc.Title = type_node.Caption;
-                                               doc.HotText = typename;
-                                               doc.Url = url;
-                                               doc.FullTitle = full;
-
-                                               var node_sel = xdoc.Root.Element ("Docs");
-                                               text.Clear ();
-                                               GetTextFromNode (node_sel, text);
-                                               doc.Text = text.ToString ();
-
-                                               text.Clear ();
-                                               GetExamples (node_sel, text);
-                                               doc.Examples = text.ToString ();
-
-                                               writer.AddDocument (doc.LuceneDoc);
-                                               var exportParsable = doc_tag[0] == 'C' && (ns_node.Caption.StartsWith ("MonoTouch") || ns_node.Caption.StartsWith ("MonoMac"));
-
-                                               //Add docs for contructors, methods, etc.
-                                               foreach (Node c in type_node.Nodes) { // c = Constructors || Fields || Events || Properties || Methods || Operators
-                                                       if (c.Element == "*")
-                                                               continue;
-                                                       const float innerTypeBoost = 0.2f;
-
-                                                       IEnumerable<Node> ncnodes = c.Nodes;
-                                                       // The rationale is that we need to properly handle method overloads
-                                                       // so for those method node which have children, flatten them
-                                                       if (c.Caption == "Methods") {
-                                                               ncnodes = ncnodes
-                                                                       .Where (n => n.Nodes == null || n.Nodes.Count == 0)
-                                                                       .Concat (ncnodes.Where (n => n.Nodes.Count > 0).SelectMany (n => n.Nodes));
-                                                       } else if (c.Caption == "Operators") {
-                                                               ncnodes = ncnodes
-                                                                       .Where (n => !n.Caption.EndsWith ("Conversion"))
-                                                                       .Concat (ncnodes.Where (n => n.Caption.EndsWith ("Conversion")).SelectMany (n => n.Nodes));
-                                                       }
-
-                                                       var prematchedMembers = xdoc.Root.Element ("Members").Elements ("Member").ToLookup (n => (string)n.Attribute ("MemberName"), n => n);
-
-                                                       foreach (Node nc in ncnodes) {
-                                                               var docsNode = GetDocsFromCaption (xdoc, c.Caption[0] == 'C' ? ".ctor" : nc.Caption, c.Caption[0] == 'O', prematchedMembers);
-                                                               if (docsNode == null) {
-                                                                       Console.Error.WriteLine ("Problem: {0}", nc.PublicUrl);
-                                                                       continue;
-                                                               }
-
-                                                               SearchableDocument doc_nod = searchDoc.Reset ();
-                                                               doc_nod.Title = LargeName (nc) + " " + EtcKindToCaption (c.Caption[0]);
-                                                               doc_nod.FullTitle = ns_node.Caption + '.' + typename + "::" + nc.Caption;
-                                                               doc_nod.HotText = string.Empty;
-
-                                                               /* Disable constructors hottext indexing as it's often "polluting" search queries
-                                                                  because it has the same hottext than standard types */
-                                                               if (c.Caption != "Constructors") {
-                                                                       //dont add the parameters to the hottext
-                                                                       int ppos = nc.Caption.IndexOf ('(');
-                                                                       doc_nod.HotText = ppos != -1 ? nc.Caption.Substring (0, ppos) : nc.Caption;
-                                                               }
-
-                                                               var urlnc = nc.PublicUrl;
-                                                               doc_nod.Url = urlnc;
-
-                                                               text.Clear ();
-                                                               GetTextFromNode (docsNode, text);
-                                                               doc_nod.Text = text.ToString ();
-
-                                                               text.Clear ();
-                                                               GetExamples (docsNode, text);
-                                                               doc_nod.Examples = text.ToString ();
-
-                                                               Document lucene_doc = doc_nod.LuceneDoc;
-                                                               lucene_doc.Boost = innerTypeBoost;
-                                                               writer.AddDocument (lucene_doc);
-
-                                                               // Objective-C binding specific parsing of [Export] attributes
-                                                               if (exportParsable) {
-                                                                       try {
-                                                                               var exports = docsNode.Parent.Elements ("Attributes").Elements ("Attribute").Elements ("AttributeName")
-                                                                                       .Select (a => (string)a).Where (txt => txt.Contains ("Foundation.Export"));
-
-                                                                               foreach (var exportNode in exports) {
-                                                                                       var parts = exportNode.Split ('"');
-                                                                                       if (parts.Length != 3) {
-                                                                                               Console.WriteLine ("Export attribute not found or not usable in {0}", exportNode);
-                                                                                               continue;
-                                                                                       }
-
-                                                                                       var export = parts[1];
-                                                                                       var export_node = searchDoc.Reset ();
-                                                                                       export_node.Title = export + " Export";
-                                                                                       export_node.FullTitle = ns_node.Caption + '.' + typename + "::" + export;
-                                                                                       export_node.Url = urlnc;
-                                                                                       export_node.HotText = export;
-                                                                                       export_node.Text = string.Empty;
-                                                                                       export_node.Examples = string.Empty;
-                                                                                       lucene_doc = export_node.LuceneDoc;
-                                                                                       lucene_doc.Boost = innerTypeBoost;
-                                                                                       writer.AddDocument (lucene_doc);
-                                                                               }
-                                                                       } catch (Exception e){
-                                                                               Console.WriteLine ("Problem processing {0} for MonoTouch/MonoMac exports\n\n{0}", e);
-                                                                       }
-                                                               }
-                                                       }
-                                               }
-                                       // doc_tag == "Enumeration"
-                                       } else if (doc_tag[0] == 'E'){
-                                               var members = xdoc.Root.Element ("Members").Elements ("Member");
-                                               if (members == null)
-                                                       continue;
-
-                                               text.Clear ();
-                                               foreach (var member_node in members) {
-                                                       string enum_value = (string)member_node.Attribute ("MemberName");
-                                                       text.Append (enum_value);
-                                                       text.Append (" ");
-                                                       GetTextFromNode (member_node.Element ("Docs"), text);
-                                                       text.AppendLine ();
-                                               }
-
-                                               SearchableDocument doc = searchDoc.Reset ();
-
-                                               text.Clear ();
-                                               GetExamples (xdoc.Root.Element ("Docs"), text);
-                                               doc.Examples = text.ToString ();
-
-                                               doc.Title = type_node.Caption;
-                                               doc.HotText = (string)xdoc.Root.Attribute ("Name");
-                                               doc.FullTitle = full;
-                                               doc.Url = url;
-                                               doc.Text = text.ToString();
-                                               writer.AddDocument (doc.LuceneDoc);
-                                       // doc_tag == "Delegate"
-                                       } else if (doc_tag[0] == 'D'){
-                                               SearchableDocument doc = searchDoc.Reset ();
-                                               doc.Title = type_node.Caption;
-                                               doc.HotText = (string)xdoc.Root.Attribute ("Name");
-                                               doc.FullTitle = full;
-                                               doc.Url = url;
-
-                                               var node_sel = xdoc.Root.Element ("Docs");
-
-                                               text.Clear ();
-                                               GetTextFromNode (node_sel, text);
-                                               doc.Text = text.ToString();
-
-                                               text.Clear ();
-                                               GetExamples (node_sel, text);
-                                               doc.Examples = text.ToString();
-
-                                               writer.AddDocument (doc.LuceneDoc);
-                                       }
-                               }
-                       }
-               }
-
-               string GetKindFromCaption (string s)
-               {
-                       int p = s.LastIndexOf (' ');
-                       if (p > 0)
-                               return s.Substring (p + 1);
-                       return null;
-               }
-
-               // Extract the interesting text from the docs node
-               void GetTextFromNode (XElement n, StringBuilder sb)
-               {
-                       // Include the text content of the docs
-                       sb.AppendLine (n.Value);
-                       foreach (var tag in n.Descendants ())
-                               //include the url to which points the see tag and the name of the parameter
-                               if ((tag.Name.LocalName.Equals ("see", StringComparison.Ordinal) || tag.Name.LocalName.Equals ("paramref", StringComparison.Ordinal))
-                                   && tag.HasAttributes)
-                                       sb.AppendLine ((string)tag.Attributes ().First ());
-               }
-
-               // Extract the code nodes from the docs
-               void GetExamples (XElement n, StringBuilder sb)
-               {
-                       foreach (var code in n.Descendants ("code"))
-                               sb.Append ((string)code);
-               }
-
-               // Extract a large name for the Node
-               static string LargeName (Node matched_node)
-               {
-                       string[] parts = matched_node.GetInternalUrl ().Split('/', '#');
-                       if (parts.Length == 3 && parts[2] != String.Empty) //List of Members, properties, events, ...
-                               return parts[1] + ": " + matched_node.Caption;
-                       else if(parts.Length >= 4) //Showing a concrete Member, property, ...
-                               return parts[1] + "." + matched_node.Caption;
-                       else
-                               return matched_node.Caption;
-               }
-
-               XElement GetMemberFromCaption (XDocument xdoc, string caption, bool isOperator, ILookup<string, XElement> prematchedMembers)
-               {
-                       string name;
-                       IList<string> args;
-                       var doc = xdoc.Root.Element ("Members").Elements ("Member");
-
-                       if (isOperator) {
-                               // The first case are explicit and implicit conversion operators which are grouped specifically
-                               if (caption.IndexOf (" to ") != -1) {
-                                       var convArgs = caption.Split (new[] { " to " }, StringSplitOptions.None);
-                                       return doc
-                                               .First (n => (AttrEq (n, "MemberName", "op_Explicit") || AttrEq (n, "MemberName", "op_Implicit"))
-                                                       && ((string)n.Element ("ReturnValue").Element ("ReturnType")).Equals (convArgs[1], StringComparison.Ordinal)
-                                                       && AttrEq (n.Element ("Parameters").Element ("Parameter"), "Type", convArgs[0]));
-                               } else {
-                                       return doc.First (m => AttrEq (m, "MemberName", "op_" + caption));
-                               }
-                       }
-
-                       TryParseCaption (caption, out name, out args);
-
-                       if (!string.IsNullOrEmpty (name)) { // Filter member by name
-                               var prematched = prematchedMembers[name];
-                               doc = prematched.Any () ? prematched : doc.Where (m => AttrEq (m, "MemberName", name));
-                       }
-                       if (args != null && args.Count > 0) // Filter member by its argument list
-                               doc = doc.Where (m => m.Element ("Parameters").Elements ("Parameter").Attributes ("Type").Select (a => (string)a).SequenceEqual (args));
-
-                       return doc.First ();
-               }
-
-               XElement GetDocsFromCaption (XDocument xdoc, string caption, bool isOperator, ILookup<string, XElement> prematchedMembers)
-               {
-                       return GetMemberFromCaption (xdoc, caption, isOperator, prematchedMembers).Element ("Docs");
-               }
-
-               // A simple stack-based parser to detect single type definition separated by commas
-               IEnumerable<string> ExtractArguments (string rawArgList)
-               {
-                       var sb = new System.Text.StringBuilder ();
-                       int genericDepth = 0;
-                       int arrayDepth = 0;
-
-                       for (int i = 0; i < rawArgList.Length; i++) {
-                               char c = rawArgList[i];
-                               switch (c) {
-                               case ',':
-                                       if (genericDepth == 0 && arrayDepth == 0) {
-                                               yield return sb.ToString ();
-                                               sb.Clear ();
-                                               continue;
-                                       }
-                                       break;
-                               case '<':
-                                       genericDepth++;
-                                       break;
-                               case '>':
-                                       genericDepth--;
-                                       break;
-                               case '[':
-                                       arrayDepth++;
-                                       break;
-                               case ']':
-                                       arrayDepth--;
-                                       break;
-                               }
-                               sb.Append (c);
-                       }
-                       if (sb.Length > 0)
-                               yield return sb.ToString ();
-               }
-
-               void TryParseCaption (string caption, out string name, out IList<string> argList)
-               {
-                       name = null;
-                       argList = null;
-                       int parenIdx = caption.IndexOf ('(');
-                       // In case of simple name, there is no need for processing
-                       if (parenIdx == -1) {
-                               name = caption;
-                               return;
-                       }
-                       name = caption.Substring (0, parenIdx);
-                       // Now we gather the argument list if there is any
-                       var rawArgList = caption.Substring (parenIdx + 1, caption.Length - parenIdx - 2); // Only take what's inside the parens
-                       if (string.IsNullOrEmpty (rawArgList))
-                               return;
-
-                       argList = ExtractArguments (rawArgList).Select (arg => arg.Trim ()).ToList ();
-               }
-
-               bool AttrEq (XElement element, string attributeName, string expectedValue)
-               {
-                       return ((string)element.Attribute (attributeName)).Equals (expectedValue, StringComparison.Ordinal);
-               }
-       }
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/providers/ecmaspec-provider.cs b/mcs/tools/monkeydoc/Monkeydoc/providers/ecmaspec-provider.cs
deleted file mode 100644 (file)
index 6b4c050..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-//
-// The ecmaspec provider is for ECMA specifications
-//
-// Authors:
-//     John Luke (jluke@cfl.rr.com)
-//     Ben Maurer (bmaurer@users.sourceforge.net)
-//
-// Use like this:
-//   mono assembler.exe --ecmaspec DIRECTORY --out name
-//
-
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.Text;
-using System.Xml.XPath;
-using System.Xml.Xsl;
-using System.Xml;
-using System.Collections.Generic;
-using Lucene.Net.Index;
-using Lucene.Net.Documents;
-
-namespace MonkeyDoc.Providers
-{
-       public class EcmaSpecProvider : Provider
-       {
-               string basedir;
-       
-               public EcmaSpecProvider (string base_directory)
-               {
-                       basedir = base_directory;
-                       if (!Directory.Exists (basedir))
-                               throw new DirectoryNotFoundException (String.Format ("The directory `{0}' does not exist", basedir));
-               }
-       
-               public override void PopulateTree (Tree tree)
-               {
-                       XPathNavigator n = new XPathDocument (Path.Combine (basedir, "toc.xml")).CreateNavigator ();
-                       n.MoveToRoot ();
-                       n.MoveToFirstChild ();
-                       PopulateNode (n.SelectChildren ("node", ""), tree.RootNode);
-               }
-       
-               void PopulateNode (XPathNodeIterator nodes, Node treeNode)
-               {
-                       foreach (XPathNavigator n in nodes) {
-                               string secNumber = n.GetAttribute ("number", "");
-                               string secName = n.GetAttribute ("name", "");
-
-                               var storage = treeNode.Tree.HelpSource.Storage;
-                               using (var file = File.OpenRead (Path.Combine (basedir, secNumber + ".xml")))
-                                       storage.Store (secNumber, file);
-
-                               Node thisNode = treeNode.GetOrCreateNode (secNumber + ": " + secName, "ecmaspec:" + secNumber);
-                       
-                               if (n.HasChildren)
-                                       PopulateNode (n.SelectChildren ("node", ""), thisNode);
-                       }
-               }
-
-               public override void CloseTree (HelpSource hs, Tree tree)
-               {
-               }
-       }
-
-       public class EcmaSpecHelpSource : HelpSource
-       {
-               const string EcmaspecPrefix = "ecmaspec:";
-               const string TocPart = "%toc"; // What is returned as TocXml
-               const string SpecPart = "%spec"; // What is returned as Ecmaspec
-
-               public EcmaSpecHelpSource (string base_file, bool create) : base (base_file, create)
-               {
-               }
-
-               public override DocumentType GetDocumentTypeForId (string id, out Dictionary<string, string> extraParams)
-               {
-                       extraParams = null;
-                       return id.EndsWith (TocPart) ? DocumentType.TocXml : DocumentType.EcmaSpecXml;
-               }
-
-               public override bool IsGeneratedContent (string id)
-               {
-                       return id == "root:" || id.EndsWith (TocPart);
-               }
-
-               public override bool IsMultiPart (string id, out IEnumerable<string> parts)
-               {
-                       if (id == "root:" || id.EndsWith (TocPart) || id.EndsWith (SpecPart)) {
-                               parts = null;
-                               return false;
-                       }
-                       parts = MakeMultiPart (id);
-                       return true;
-               }
-
-               IEnumerable<string> MakeMultiPart (string baseId)
-               {
-                       yield return baseId + SpecPart;
-                       yield return baseId + TocPart;
-               }
-
-               public override string GetText (string id)
-               {
-                       Node n = id == "root:" ? Tree.RootNode : MatchNode (EcmaspecPrefix + id.Substring (0, id.Length - TocPart.Length));
-                       if (n == null)
-                               throw new ArgumentException ("id", string.Format ("{0} -> {1}", id, EcmaspecPrefix + id.Substring (0, id.Length - TocPart.Length)));
-                       return TreeDumper.ExportToTocXml (n, "C# Language Specification", "In this section:");
-               }
-
-               public override Stream GetHelpStream (string id)
-               {
-                       return id.EndsWith (SpecPart) ? base.GetHelpStream (id.Substring (0, id.IndexOf (SpecPart))) : base.GetHelpStream (id);
-               }
-       
-               public override void PopulateSearchableIndex (IndexWriter writer) 
-               {
-                       foreach (Node n in Tree.RootNode.Nodes)
-                               AddDocuments (writer, n);
-               }
-
-               protected override string UriPrefix {
-                       get {
-                               return EcmaspecPrefix;
-                       }
-               }
-
-               void AddDocuments (IndexWriter writer, Node node) 
-               {
-                       string url = node.PublicUrl;
-                       Stream file_stream = GetHelpStream (url.Substring (9));
-                       if (file_stream == null) //Error
-                               return;
-                       XmlDocument xdoc = new XmlDocument ();
-                       xdoc.Load (new XmlTextReader (file_stream));
-
-                       //Obtain the title
-                       XmlNode nelem = xdoc.DocumentElement;
-                       string title = nelem.Attributes["number"].Value + ": " + nelem.Attributes["title"].Value;
-
-                       //Obtain the text
-                       StringBuilder s = new StringBuilder ();
-                       GetTextNode (nelem, s);
-                       string text = s.ToString ();
-
-                       //Obtain the examples
-                       StringBuilder s2 = new StringBuilder ();
-                       GetExamples (nelem, s2);
-                       string examples = s2.ToString ();
-
-                       //Write to the Lucene Index all the parts
-                       SearchableDocument doc = new SearchableDocument ();
-                       doc.Title = title;
-                       doc.HotText = title.Substring (title.IndexOf (':')); 
-                       doc.Url = url;
-                       doc.Text = text;
-                       doc.Examples = examples;
-                       writer.AddDocument (doc.LuceneDoc);
-               
-                       if (node.IsLeaf)
-                               return;
-
-                       foreach (Node n in node.Nodes)
-                               AddDocuments (writer, n);
-               }
-
-               void GetTextNode (XmlNode n, StringBuilder s) 
-               {
-                       //dont include c# code
-                       if (n.Name == "code_example")
-                               return;
-                       //include all text from nodes
-                       if (n.NodeType == XmlNodeType.Text)
-                               s.Append (n.Value);
-               
-                       //recursively explore all nodes
-                       if (n.HasChildNodes)
-                               foreach (XmlNode n_child in n.ChildNodes)
-                                       GetTextNode (n_child, s);
-               }
-
-               void GetExamples (XmlNode n, StringBuilder s)
-               {
-                       if (n.Name == "code_example") {
-                               if (n.FirstChild.Name == "#cdata-section")
-                                       s.Append (n.FirstChild.Value);
-                       } else {
-                               if (n.HasChildNodes)
-                                       foreach (XmlNode n_child in n.ChildNodes)
-                                               GetExamples (n_child, s);
-                       }
-               }
-       }
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/providers/ecmauncompiled-provider.cs b/mcs/tools/monkeydoc/Monkeydoc/providers/ecmauncompiled-provider.cs
deleted file mode 100644 (file)
index 272eb64..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-using System;
-using System.Linq;
-using System.IO;
-using System.Text;
-using System.Xml;
-using System.Xml.Linq;
-using System.Collections.Generic;
-
-using Lucene.Net.Index;
-using Lucene.Net.Documents;
-
-using MonkeyDoc.Ecma;
-using MonkeyDoc.Storage;
-using Mono.Utilities;
-
-namespace MonkeyDoc.Providers
-{
-       public class EcmaUncompiledHelpSource : EcmaHelpSource
-       {
-               readonly DirectoryInfo basedir;
-               readonly string basedoc;
-
-               public readonly string BasePath;
-
-               public new string Name {
-                       get;
-                       private set;
-               }
-       
-               /* base_file: the directory containing the index.xml file, usually in Mono land .../Documentation/en
-                * markName: if true, we encase the node caption with [] to clearly mark it's from an uncompiled source
-                */
-               public EcmaUncompiledHelpSource (string base_file, bool markName = true) : base ()
-               {
-                       basedir = new DirectoryInfo (base_file);
-                       BasePath = basedir.FullName;
-               
-                       basedoc = Path.Combine (basedir.FullName, "index.xml");
-               
-                       Name = ((string)XDocument.Load (basedoc).Root.Element ("Title")) ?? "UnnamedUncompiledSource";
-                       if (markName)
-                               Name = '[' + Name + ']';
-                       Tree.RootNode.Caption = Name;
-
-                       Func<XElement, string> indexGenerator = type => {
-                               var nsName = (string)type.Parent.Attribute ("Name");
-                               var typeName = (string)type.Attribute ("Name");
-                               return Path.ChangeExtension (nsName + '/' + typeName, ".xml");
-                       };
-
-                       this.Storage = new UncompiledDocStorage (BasePath);
-
-                       EcmaDoc.PopulateTreeFromIndexFile (basedoc, Tree, null, null);
-               }
-
-               protected override string UriPrefix {
-                       get {
-                               return "uncompiled:";
-                       }
-               }
-       }
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/providers/error-provider.cs b/mcs/tools/monkeydoc/Monkeydoc/providers/error-provider.cs
deleted file mode 100644 (file)
index 2acb26e..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-//
-// error-provider.cs
-//
-// Author:
-//   Ben Maurer (bmaurer@users.sourceforge.net)
-//
-// (C) 2003 Ben Maurer
-// Copyright 2003-2011 Novell
-// Copyright 2011 Xamarin Inc
-//
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-using System.Xml;
-using System.Xml.Serialization;
-using System.Linq;
-using Lucene.Net.Index;
-using Lucene.Net.Documents;
-
-namespace MonkeyDoc.Providers
-{
-       public class ErrorProviderConfig
-       {
-               public string FilesPath;
-               public string Match;
-               public int ErrorNumSubstringStart;
-               public int ErrorNumSubstringLength;
-               public string FriendlyFormatString;
-
-               public override string ToString ()
-               {
-                       var sb = new StringBuilder ();
-                       var w = new StringWriter (sb);
-                       
-                       w.WriteLine ("FilesPath: {0}", FilesPath);
-                       w.WriteLine ("Match: {0}", Match);
-                       w.WriteLine ("Error Number Substring: {0} Length:{1}", ErrorNumSubstringStart, ErrorNumSubstringLength);
-                       w.WriteLine ("FriendlyFormatString: {0}", FriendlyFormatString);
-                       
-                       return w.ToString ();
-               }
-               
-               public Dictionary<string, ErrorDocumentation> Compile (HelpSource hs)
-               {
-                       string[] files = Directory.GetFiles (FilesPath, Match);
-                       var ret = new Dictionary<string, ErrorDocumentation> ();
-                       
-                       foreach (string s in files) {
-                               ErrorDocumentation d;
-                               int errorNum = 0;
-
-                               try {
-                                       errorNum = int.Parse (Path.GetFileName (s).Substring (ErrorNumSubstringStart, ErrorNumSubstringLength));
-                               } catch {
-                                       Console.WriteLine ("Ignoring file {0}", s);
-                               }
-                               
-                               string errorName = String.Format (FriendlyFormatString, errorNum);
-                               
-                               if (!ret.TryGetValue (errorName, out d))
-                                       ret[errorName] = d = new ErrorDocumentation (errorName);
-
-                               if (d.Details == null) {
-                                       string xmlFile = Path.ChangeExtension (s, "xml");
-                                       if (File.Exists (xmlFile)) {
-                                               XmlSerializer cfgRdr = new XmlSerializer (typeof (ErrorDetails));
-                                               d.Details = (ErrorDetails)cfgRdr.Deserialize (new XmlTextReader (xmlFile));
-                                       }
-                               }
-                               // Encoding is same as used in MCS, so we will be able to do all those files
-                               using (StreamReader reader = new StreamReader (s, Encoding.GetEncoding (28591))) {
-                                       d.Examples.Add (reader.ReadToEnd ());
-                               }
-                       }
-                       
-                       return ret;
-               }
-       }
-
-       public class ErrorDocumentation
-       {
-               public string ErrorName;
-               public ErrorDetails Details;
-               public List<string> Examples = new List<string> ();
-               
-               public ErrorDocumentation () {}
-               public ErrorDocumentation (string ErrorName)
-               {
-                       this.ErrorName = ErrorName;
-               }
-       }
-       
-       public class ErrorDetails
-       {
-               public XmlNode Summary;
-               public XmlNode Details;
-       }
-
-       public class ErrorProvider : Provider
-       {
-               ErrorProviderConfig config;
-               
-               public ErrorProvider (string configFile)
-               {
-                       config = ReadConfig (configFile);
-               }
-               
-               public static ErrorProviderConfig ReadConfig (string file)
-               {
-                       XmlSerializer cfgRdr = new XmlSerializer (typeof (ErrorProviderConfig));
-                       ErrorProviderConfig ret = (ErrorProviderConfig)cfgRdr.Deserialize (new XmlTextReader (file));
-                       // handle path rel to the config file
-                       ret.FilesPath = Path.Combine (Path.GetDirectoryName (file), ret.FilesPath);
-                       return ret;
-               }
-       
-               public override void PopulateTree (Tree tree)
-               {
-                       // everything is done in CloseTree so we can pack
-               }
-       
-               public override void CloseTree (HelpSource hs, Tree tree)
-               {
-                       var entries = config.Compile (hs);
-                       MemoryStream ms = new MemoryStream ();
-                       XmlSerializer writer = new XmlSerializer (typeof (ErrorDocumentation));
-                       
-                       foreach (var de in entries) {
-                               ErrorDocumentation d = de.Value;
-                               string s = de.Key;
-
-                               tree.RootNode.GetOrCreateNode (s, "error:" + s);
-                               
-                               writer.Serialize (ms, d);
-                               ms.Position = 0;
-                               hs.Storage.Store (s, ms);
-                               ms.SetLength (0);
-                       }
-                       
-                       tree.RootNode.Sort ();
-               }
-       }
-       
-       public class ErrorHelpSource : HelpSource
-       {               
-               public ErrorHelpSource (string base_file, bool create) : base (base_file, create)
-               {
-               }
-
-               public override string GetText (string id)
-               {
-                       return TreeDumper.ExportToTocXml (Tree.RootNode, "Compiler Error Reference", "In this section:");
-               }
-               
-               protected override string UriPrefix {
-                       get {
-                               return "error:";
-                       }
-               }
-
-               public override bool IsGeneratedContent (string id)
-               {
-                       return id == "root:";
-               }
-
-               public override DocumentType GetDocumentTypeForId (string id, out Dictionary<string, string> extraParams)
-               {
-                       extraParams = null;
-                       return id == "root:" ? DocumentType.TocXml : DocumentType.ErrorXml;
-               }
-
-               public override string GetInternalIdForUrl (string url, out Node node)
-               {
-                       var result = base.GetInternalIdForUrl (url, out node);
-                       return result.ToLower ();
-               }
-               
-               public override void PopulateIndex (IndexMaker index_maker)
-               {
-                       foreach (Node n in Tree.RootNode.Nodes)
-                               index_maker.Add (n.Caption, n.Caption, n.Element);
-               }
-
-               public override void PopulateSearchableIndex (IndexWriter writer) 
-               {
-                       foreach (Node n in Tree.RootNode.Nodes) {
-                               XmlSerializer reader = new XmlSerializer (typeof (ErrorDocumentation));
-                               ErrorDocumentation d = (ErrorDocumentation)reader.Deserialize (GetHelpStream (n.Element.Substring (6)));
-                               SearchableDocument doc = new SearchableDocument ();
-                               doc.Title = d.ErrorName;
-                               doc.Url = n.Element;
-                               doc.Text = d.Details != null ? d.Details.ToString () : string.Empty;
-                               doc.Examples = d.Examples.Cast<string> ().Aggregate ((e1, e2) => e1 + Environment.NewLine + e2);
-                               doc.HotText = d.ErrorName;
-                               writer.AddDocument (doc.LuceneDoc);
-                       }
-               }
-       }
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/providers/man-provider.cs b/mcs/tools/monkeydoc/Monkeydoc/providers/man-provider.cs
deleted file mode 100755 (executable)
index 32b9c93..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-//
-// A provider to display man pages
-//
-// Authors:
-//   Johannes Roith <johannes@roith.de>
-//   Jonathan Pryor <jpryor@novell.com>
-//
-// (C) 2008 Novell, Inc.
-
-using System;
-using System.IO;
-using System.Text;
-using System.Xml;
-using System.Linq;
-using System.Collections.Generic;
-
-namespace MonkeyDoc.Providers
-{
-       public class ManProvider : Provider
-       {
-               string[] tocFiles;
-       
-               public ManProvider (string[] handbookTocFiles)
-               {
-                       tocFiles = handbookTocFiles;
-
-                       // huh...
-                       if (!File.Exists (tocFiles[0]))
-                               throw new FileNotFoundException (String.Format ("The table of contents, `{0}' does not exist", tocFiles[0]));
-               }
-
-               public override void PopulateTree (Tree tree)
-               {
-                       foreach(string TocFile in tocFiles) {
-                               XmlDocument doc = new XmlDocument();
-                               doc.Load (TocFile);
-
-                               XmlNodeList nodeList = doc.GetElementsByTagName("manpage");
-                               Node nodeToAddChildrenTo = tree.RootNode;
-                               var storage = nodeToAddChildrenTo.Tree.HelpSource.Storage;
-
-                               foreach (XmlNode node in nodeList) {
-
-                                       XmlAttribute name = node.Attributes["name"];
-                                       XmlAttribute page = node.Attributes["page"];
-
-                                       if (name == null || page == null) continue;
-
-                                       if (!File.Exists (page.Value))
-                                               continue;
-
-                                       string target = "man:" + name.Value;
-                                       nodeToAddChildrenTo.CreateNode (name.Value, target);
-
-                                       if (File.Exists (page.Value))
-                                               storage.Store (name.Value, File.OpenRead (page.Value));
-                               }
-                       }
-               }
-
-               public override void CloseTree (HelpSource hs, Tree tree)
-               {
-               }
-       }
-
-       public class ManHelpSource : HelpSource
-       {
-               const string ManPrefix = "man:";
-               Dictionary<string, Node> nodesMap;
-
-               public ManHelpSource (string base_file, bool create) : base (base_file, create)
-               {
-                       nodesMap = Tree.RootNode.Nodes.ToDictionary (n => n.Element);
-               }
-
-               // Since man always has a flat tree and rather small amount of item
-               // we store them in a dictionary
-               public override Node MatchNode (string url)
-               {
-                       Node result;
-                       return nodesMap.TryGetValue (url, out result) ? result : null;
-               }
-
-               public override DocumentType GetDocumentTypeForId (string id, out Dictionary<string, string> extraParams)
-               {
-                       extraParams = null;
-                       return id == "root:" ? DocumentType.TocXml : DocumentType.Man;
-               }
-
-               public override bool IsGeneratedContent (string id)
-               {
-                       return id == "root:";
-               }
-       
-               public override string GetText (string url)
-               {
-                       return TreeDumper.ExportToTocXml (Tree.RootNode, "Mono Documentation Library", "Available man pages:");
-               }
-
-               protected override string UriPrefix {
-                       get {
-                               return ManPrefix;
-                       }
-               }
-       }
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/providers/simple-provider.cs b/mcs/tools/monkeydoc/Monkeydoc/providers/simple-provider.cs
deleted file mode 100644 (file)
index e567dc1..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-//
-// The simple provider is an example provider
-//
-// Author:
-//   Miguel de Icaza (miguel@ximian.com)
-//
-// Use like this:
-//   mono assembler.exe --simple DIRECTORY --out name
-//
-// Then create a .source file in your sources directory, and copy
-// name.tree and name.zip to the sources directory.
-//
-// To view the tree generated, use:
-//   mono dump.exe name.tree
-//
-namespace Monodoc {
-using System;
-using System.IO;
-using System.Text;
-
-//
-// The simple provider generates the information source
-//
-public class SimpleProvider : Provider {
-       string basedir;
-       
-       public SimpleProvider (string base_directory)
-       {
-               basedir = base_directory;
-               if (!Directory.Exists (basedir))
-                       throw new FileNotFoundException (String.Format ("The directory `{0}' does not exist", basedir));
-       }
-
-       public override void PopulateTree (Tree tree)
-       {
-               Node top = tree.LookupNode ("Directory at: " + basedir, "simple:");
-               
-               foreach (string dir in Directory.GetDirectories (basedir)){
-                       string url = Path.GetFileName (dir);
-                       Node n = top.LookupNode ("Dir: " + url, url);
-                       PopulateDir (n, dir);
-               }
-       }
-
-#pragma warning disable 219
-       void PopulateDir (Node me, string dir)
-       {
-               Console.WriteLine ("Adding: " + dir);
-               foreach (string child_dir in Directory.GetDirectories (dir)){
-                       string url = Path.GetFileName (child_dir);
-                       Node n = me.LookupNode ("Dir: " + url, "simple-directory:" + url);
-                       PopulateDir (me, child_dir);
-               }
-
-               foreach (string file in Directory.GetFiles (dir)){
-                       Console.WriteLine ("   File: " + file);
-                       string file_code = me.tree.HelpSource.PackFile (file);
-
-                       //
-                       // The url element encoded for the file is:
-                       //  originalfilename#CODE
-                       //
-                       // The code is assigned to us after the file has been packaged
-                       // We use the original-filename later to render html or text files
-                       //
-                       Node n = me.LookupNode (Path.GetFileName (file), file + "#" + file_code);
-                       
-               }
-       }
-
-       public override void CloseTree (HelpSource hs, Tree tree)
-       {
-       }
-}
-
-//
-// The HelpSource is used during the rendering phase.
-//
-
-public class SimpleHelpSource : HelpSource {
-       Encoding enc;
-       
-       public SimpleHelpSource (string base_file, bool create) : base (base_file, create)
-       {
-               enc = new UTF8Encoding (false, false);
-       }
-
-       public override string GetText (string url, out Node match_node)
-       {
-               match_node = null;
-
-               string c = GetCachedText (url);
-               if (c != null)
-                       return c;
-
-               if (url.StartsWith ("simple:") || url.StartsWith ("simple-directory:"))
-                       return GetTextFromUrl (url);
-
-               return null;
-       }
-
-       string GetTextFromUrl (string url)
-       {
-               // Remove "simple:" prefix
-               url = url.Substring (7);
-
-               if (url.StartsWith ("simple-directory:"))
-                       return String.Format ("<html>This is a directory entry point: {0} </html>",
-                                             url.Substring (17));
-
-               // Otherwise the last element of the url is the file code we got.
-               int pound = url.LastIndexOf ("#");
-               string code;
-               if (pound == -1)
-                       code = url;
-               else
-                       code = url.Substring (pound+1);
-
-
-               Stream s = GetHelpStream (code);
-               if (s == null)
-                       return String.Format ("<html>No stream for this node: {0} </html>", url);
-
-               //
-               // Now, get the file type
-               //
-               int slash = url.LastIndexOf ("/");
-               string fname = url.Substring (slash + 1, pound - slash - 1).ToLower ();
-
-               if (fname.EndsWith (".html") || fname.EndsWith (".htm")){
-                       TextReader r = new StreamReader (s, enc);
-                       return r.ReadToEnd ();
-               }
-
-               if (fname.EndsWith (".png") || fname.EndsWith (".jpg") ||
-                   fname.EndsWith (".jpeg") || fname.EndsWith (".gif")){
-                       return "<html>Image file, have not implemented rendering this yet</html>";
-               }
-
-               // Convert text to HTML
-               StringBuilder result = new StringBuilder ("<html>");
-               TextReader reader = new StreamReader (s, enc);
-               string line;
-               
-               while ((line = reader.ReadLine ()) != null){
-                       result.Append (line);
-                       result.Append ("<br>");
-               }
-               result.Append ("<html>");
-               return result.ToString ();
-       }
-}
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/providers/xhtml-provider.cs b/mcs/tools/monkeydoc/Monkeydoc/providers/xhtml-provider.cs
deleted file mode 100644 (file)
index 9e7c0f2..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-//
-// A provider that uses Windows help file xhtml TOC files and looks for the
-// referenced documents to create the help source. 
-//
-// Authors:
-// Copyright 2003 Lee Mallabone <gnome@fonicmonkey.net>
-//   Johannes Roith <johannes@roith.de>
-//   Miguel de Icaza <miguel@ximian.com>
-
-using System;
-using System.IO;
-using System.Collections.Generic;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Xml;
-
-namespace MonkeyDoc.Providers
-{
-       public class XhtmlProvider : Provider
-       {
-               string tocFile;
-       
-               public XhtmlProvider (string handbookTocFile)
-               {
-                       tocFile = handbookTocFile;
-                       if (!File.Exists (tocFile))
-                               throw new FileNotFoundException (String.Format ("The table of contents, `{0}' does not exist", tocFile));               
-               }
-
-               public override void PopulateTree (Tree tree)
-               {
-                       //new SimpleHandbookTOCParser(tree, tocFile);
-                       // TODO: port it
-               }
-
-               public override void CloseTree (HelpSource hs, Tree tree)
-               {
-               }
-       }
-
-       public class XhtmlHelpSource : HelpSource
-       {
-               public XhtmlHelpSource (string base_file, bool create) : base (base_file, create)
-               {
-
-               }
-
-               const string XhtmlPrefix = "xhtml:";
-
-               protected override string UriPrefix {
-                       get {
-                               return XhtmlPrefix;
-                       }
-               }
-               
-               public override DocumentType GetDocumentTypeForId (string id, out Dictionary<string, string> extraArgs)
-               {
-                       extraArgs = null;
-                       return id == "root:" ? DocumentType.TocXml : DocumentType.MonoBook;
-               }
-
-               public override bool IsGeneratedContent (string id)
-               {
-                       return id == "root:";
-               }
-       
-               public override string GetText (string url)
-               {
-                       return TreeDumper.ExportToTocXml (Tree.RootNode, "Mono Handbook", string.Empty);
-               }
-
-               public static string GetAbsoluteLink(string target, string url)
-               {
-                       
-                       string value = null;
-               
-                       if (target.StartsWith ("#") ||
-                           target.StartsWith ("T:") ||
-                           target.StartsWith ("M:") ||
-                           target.StartsWith ("P:") ||
-                           target.StartsWith ("T:") ||
-                           target.StartsWith ("E:") ||
-                           target.StartsWith ("F:") ||
-                           target.StartsWith ("O:") ||
-                           target.StartsWith ("N:") ||
-                           target.StartsWith ("api:"))
-                               return null;
-               
-                       int endp = target.IndexOf(':');
-               
-                       if (endp == -1)
-                               endp = 0;
-                       string protocol = target.Substring(0, endp);
-                       switch (protocol) {
-                       case "mailto": 
-                       case "http":
-                       case "https":
-                       case "ftp":
-                       case "news":
-                       case "irc":
-                               break;
-                       default:
-                               // handle absolute urls like: /html/en/images/empty.png
-                               if (!target.StartsWith("/")) {
-                               
-                                       // url is something like "gnome/bindings/mono.html"
-                                       // This will get the path "gnome/bindings"
-                               
-                                       int slash = url.LastIndexOf ("/");
-                                       string tmpurl = url;
-                               
-                                       if (slash != -1)
-                                               tmpurl  = url.Substring(0, slash);
-                               
-                                       // Count "../" in target and go one level down
-                                       // for each in tmpurl, eventually, then remove "../".
-                               
-                                       Regex reg1 = new Regex("../");
-                                       MatchCollection matches = reg1.Matches(target);
-                               
-                                       for(int i = 1; i < matches.Count; i++) {
-                                               slash = tmpurl.LastIndexOf ("/");
-                                               if (slash != -1) 
-                                                       tmpurl  = tmpurl.Substring(0, slash);
-                                       }
-                               
-                                       target = target.Replace("../", "");
-                               
-                                       value = tmpurl + "/" + target;
-                               
-                               } else {
-                                       value = target.Substring(1, target.Length - 1);
-                               }
-                               break;
-                       }
-                       return value;
-               }
-       
-               XmlDocument RewriteLinks(XmlDocument docToProcess, string url)
-               {
-                       XmlNodeList nodeList = docToProcess.GetElementsByTagName("a");
-               
-                       foreach(XmlNode node in nodeList) {
-                       
-                               XmlElement element = (XmlElement) node;
-                       
-                               if (element.HasAttribute("href") ){
-                               
-                                       XmlAttribute href = element.GetAttributeNode("href");
-                                       string target = href.Value;
-                               
-                                       target = GetAbsoluteLink(target, url);
-                                       if (target != null) {
-                                               string newtarget = String.Format ("source-id:{0}:xhtml:{1}", SourceID, target);
-                                               href.Value = newtarget;
-                                       }
-                               }
-                       }
-
-                       nodeList = docToProcess.GetElementsByTagName("img");
-
-                       foreach(XmlNode node in nodeList) {
-                                                                                                                                    
-                               XmlElement element = (XmlElement) node;
-                                                                                                                                    
-                               if (element.HasAttribute("src") ){
-                                                                                                                                    
-                                       XmlAttribute href = element.GetAttributeNode("src");
-                                       string target = href.Value;
-                                                                                                                                    
-                                       target = GetAbsoluteLink(target, url);
-                                       if (target != null) {
-                                               string newtarget = String.Format ("source-id:{0}:xhtml:{1}", SourceID, target);
-                                               href.Value = newtarget;
-                                       }
-                               }               
-                       }
-
-                       return docToProcess;
-               }
-
-               public override void PopulateIndex (IndexMaker index_maker)
-               {
-                       PopulateIndexFromNodes (Tree.RootNode);
-               }
-
-               void PopulateIndexFromNodes (Node start)
-               {
-                       /*var nodes = start.Nodes;
-               
-                       if (nodes != null) {
-                               foreach (Node n in nodes)
-                                       PopulateIndexFromNodes (n);
-                       }*/
-               }
-       }
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/settings.cs b/mcs/tools/monkeydoc/Monkeydoc/settings.cs
deleted file mode 100644 (file)
index ad73e42..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-using System;
-using System.Configuration;
-using System.Collections.Specialized;
-
-namespace MonkeyDoc
-{
-       public static class Settings
-       {
-               static KeyValueConfigurationCollection libConfig;
-               static KeyValueConfigurationCollection exeConfig;
-
-               static Settings ()
-               {
-                       try {
-                               var config = ConfigurationManager.OpenExeConfiguration (System.Reflection.Assembly.GetExecutingAssembly ().Location);
-                               libConfig = config.AppSettings.Settings;
-                       } catch {}
-
-                       try {
-                               exeConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).AppSettings.Settings;
-                       } catch {}
-               }
-
-               public static string Get (string key) {
-                       KeyValueConfigurationElement element = null;
-                       // We check the configuration in order: app first and then library itself
-                       if (exeConfig != null)
-                               element = exeConfig[key];
-                       if (element == null && libConfig != null)
-                               element = libConfig[key];
-
-                       return element == null ? null : element.Value;
-               }
-
-               public static KeyValueConfigurationCollection AppSettings {
-                       get {
-                               return exeConfig;
-                       }
-               }
-
-               public static KeyValueConfigurationCollection LibSettings {
-                       get {
-                               return libConfig;
-                       }
-               }
-       }
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/storage.cs b/mcs/tools/monkeydoc/Monkeydoc/storage.cs
deleted file mode 100644 (file)
index 9085ff5..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-using System;
-using System.IO;
-using System.Collections.Generic;
-
-namespace MonkeyDoc
-{
-       // Define a storage mechanism for a help source
-       public interface IDocStorage : IDisposable
-       {
-               // Tell if the storage can store successive change to the doc as revision
-               bool SupportRevision { get; }
-               IDocRevisionManager RevisionManager { get; }
-
-               // Tell if the storage support modifying an existing data
-               bool SupportChange { get; }
-
-               /* Store data inside the storage backend
-                * if SupportChange is false and user try to store something with an existing id
-                * an exception will be thrown
-                * if id is null or empty, the storage will try to create an automatic id. In all
-                * case the id that has been used to store the content is returned by the method
-                */
-               string Store (string id, string text);
-               string Store (string id, byte[] data);
-               string Store (string id, Stream stream);
-
-               Stream Retrieve (string id);
-
-               IEnumerable<string> GetAvailableIds ();
-       }
-
-       public interface IDocRevisionManager
-       {
-               Stream RetrieveWithRevision (string id, string revision);
-
-               // This should be ordered by most recent first
-               IEnumerable<string> AvailableRevisionsForId (string id);
-               // This can simply be implemented with above property but it can also be
-               // a revision storage symbolic value like "HEAD"
-               string LatestRevisionForId (string id);
-
-               // A commit message for instance
-               string GetRevisionDescription (string revision);
-       }
-
-       public static class DocRevisionManagerExtensions
-       {
-               public static Stream RetrieveLatestRevision (this IDocRevisionManager revManager, string id)
-               {
-                       return revManager.RetrieveWithRevision (id, revManager.LatestRevisionForId (id));
-               }
-       }
-}
\ No newline at end of file
diff --git a/mcs/tools/monkeydoc/Monkeydoc/storage/NullStorage.cs b/mcs/tools/monkeydoc/Monkeydoc/storage/NullStorage.cs
deleted file mode 100644 (file)
index 891a965..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-using System;
-using System.IO;
-using System.Xml;
-using System.Linq;
-using System.Collections.Generic;
-
-namespace MonkeyDoc.Storage
-{
-       // A storage that doesn't store
-       public class NullStorage : IDocStorage
-       {
-               public NullStorage ()
-               {
-               }
-
-               public bool SupportRevision {
-                       get {
-                               return false;
-                       }
-               }
-
-               public IDocRevisionManager RevisionManager {
-                       get {
-                               return null;
-                       }
-               }
-
-               public bool SupportChange {
-                       get {
-                               return true;
-                       }
-               }
-
-               public string Store (string id, string text)
-               {
-                       return id;
-               }
-
-               public string Store (string id, byte[] data)
-               {
-                       return id;
-               }
-
-               public string Store (string id, Stream stream)
-               {
-                       return id;
-               }
-
-               public Stream Retrieve (string id)
-               {
-                       return null;
-               }
-
-               public IEnumerable<string> GetAvailableIds ()
-               {
-                       return Enumerable.Empty<string> (); 
-               }
-
-               public void Dispose ()
-               {
-               }
-       }
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/storage/UncompiledDocStorage.cs b/mcs/tools/monkeydoc/Monkeydoc/storage/UncompiledDocStorage.cs
deleted file mode 100644 (file)
index fe3976a..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-using System;
-using System.IO;
-using System.Linq;
-using System.Collections.Generic;
-
-namespace MonkeyDoc.Storage
-{
-       // A read-only storage to access ecma XML document based on a standard directory layout
-       // id are relative path inside the base doc directory
-       public class UncompiledDocStorage : IDocStorage
-       {
-               readonly string basePath;
-
-               public UncompiledDocStorage (string basePath)
-               {
-                       this.basePath = basePath;
-               }
-
-               public bool SupportRevision {
-                       get {
-                               return false;
-                       }
-               }
-
-               public IDocRevisionManager RevisionManager {
-                       get {
-                               return null;
-                       }
-               }
-
-               public bool SupportChange {
-                       get {
-                               return false;
-                       }
-               }
-
-               public string Store (string id, string text)
-               {
-                       throw new NotSupportedException ();
-               }
-
-               public string Store (string id, byte[] data)
-               {
-                       throw new NotSupportedException ();
-               }
-
-               public string Store (string id, Stream stream)
-               {
-                       throw new NotSupportedException ();
-               }
-
-               public Stream Retrieve (string id)
-               {
-                       var path = id;
-                       if ('/' != Path.DirectorySeparatorChar)
-                               path = path.Replace ('/', Path.DirectorySeparatorChar);
-                       return File.OpenRead (Path.Combine (basePath, path));
-               }
-
-               public IEnumerable<string> GetAvailableIds ()
-               {
-                       return Directory.EnumerateFiles (basePath, "*.xml", SearchOption.AllDirectories);
-               }
-
-               public void Dispose ()
-               {
-               }
-       }
-}
diff --git a/mcs/tools/monkeydoc/Monkeydoc/storage/ZipStorage.cs b/mcs/tools/monkeydoc/Monkeydoc/storage/ZipStorage.cs
deleted file mode 100644 (file)
index 81ed1c5..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-using System;
-using System.IO;
-using System.Xml;
-using System.Linq;
-using System.Text;
-using System.Collections.Generic;
-
-using ICSharpCode.SharpZipLib.Zip;
-
-namespace MonkeyDoc.Storage
-{
-       public class ZipStorage : IDocStorage
-       {
-               string zipFileName;
-               int code;
-               ZipOutputStream zipOutput;
-               ZipFile zipFile;
-               // SharpZipLib use linear search to map name to index, correct that a bit
-               Dictionary<string, int> entries = new Dictionary<string, int> ();
-
-               public ZipStorage (string zipFileName)
-               {
-                       this.zipFileName = zipFileName;
-               }
-
-               public bool SupportRevision {
-                       get {
-                               return false;
-                       }
-               }
-
-               public IDocRevisionManager RevisionManager {
-                       get {
-                               return null;
-                       }
-               }
-
-               public bool SupportChange {
-                       get {
-                               return true;
-                       }
-               }
-
-               public string Store (string id, string text)
-               {
-                       EnsureOutput ();
-                       SetupEntry (zipOutput, ref id);
-                       var writer = new StreamWriter (zipOutput);
-                       writer.Write (text);
-                       writer.Flush ();
-                       
-                       return id;
-               }
-
-               public string Store (string id, byte[] data)
-               {
-                       EnsureOutput ();
-                       SetupEntry (zipOutput, ref id);
-                       zipOutput.Write (data, 0, data.Length);
-                       return id;
-               }
-
-               public string Store (string id, Stream stream)
-               {
-                       EnsureOutput ();
-                       SetupEntry (zipOutput, ref id);
-                       stream.CopyTo (zipOutput);
-                       return id;
-               }
-
-               void SetupEntry (ZipOutputStream zipOutput, ref string id)
-               {
-                       if (string.IsNullOrEmpty (id))
-                               id = GetNewCode ();
-
-                       ZipEntry entry = new ZipEntry (id);
-                       zipOutput.PutNextEntry (entry);
-               }
-
-               public Stream Retrieve (string id)
-               {
-                       EnsureInput ();
-                       int index;
-                       ZipEntry entry;
-                       if (!entries.TryGetValue (id, out index) || (entry = zipFile[index]) == null)
-                               entry = zipFile.GetEntry (id);
-                       if (entry != null)
-                               return zipFile.GetInputStream (entry);
-                       else
-                               throw new ArgumentException ("id", string.Format ("'{0}' isn't a valid id for this storage", id));
-               }
-
-               public IEnumerable<string> GetAvailableIds ()
-               {
-                       EnsureInput ();
-                       return zipFile.Cast<ZipEntry> ().Select (ze => ze.Name);
-               }
-
-               void EnsureOutput ()
-               {
-                       if (zipFile != null)
-                               throw new InvalidOperationException ("This ZipStorage instance is already used in read-mode");
-                       if (zipOutput != null)
-                               return;
-                       zipOutput = new ZipOutputStream (File.Create (zipFileName));
-               }
-
-               void EnsureInput ()
-               {
-                       if (zipOutput != null)
-                               throw new InvalidOperationException ("This ZipStorage instance is already used in write-mode");
-                       if (zipFile != null)
-                               return;
-                       zipFile = new ZipFile (zipFileName);
-                       entries = Enumerable.Range (0, zipFile.Size).ToDictionary (i => zipFile[i].Name, i => i);
-               }
-
-               public void Dispose ()
-               {
-                       if (zipOutput != null)
-                               zipOutput.Dispose ();
-                       if (zipFile != null)
-                               zipFile.Close ();
-               }
-
-               string GetNewCode ()
-               {
-                       return String.Format ("{0}", code++);
-               }
-       }
-}
\ No newline at end of file