Index: demangle.d
===================================================================
--- demangle.d	(revision 390)
+++ demangle.d	(working copy)
@@ -33,7 +33,7 @@
  *  The demangled name or the original string if the name is not a mangled D
  *  name.
  */
-char[] demangle( const(char)[] buf, char[] dst = null )
+struct Demangler
 {
     // NOTE: This implementation currently only works with mangled function
     //       names as they exist in an object file.  Type names mangled via
@@ -850,7 +850,7 @@
         case 'E': // TypeEnum (E LName)
         case 'T': // TypeTypedef (T LName)
             next();
-            parseLName();
+            parseQualifiedName();
             return dst[beg .. len];
         case 'D': // TypeDelegate (D TypeFunction)
             next();
@@ -1061,7 +1061,7 @@
                 put( (cast(char*) &v)[0 .. 1] );
             }
             put( "\"" );
-            if( 'a' != tok() )
+            if( 'a' != t )
                 put( (cast(char*) &t)[0 .. 1] );
             return;
         case 'A':
@@ -1106,7 +1106,7 @@
             case 'S':
                 next();
                 if( n ) put( ", " );
-                parseLName();
+                parseQualifiedName();
                 continue;
             default:
                 return;
@@ -1227,9 +1227,21 @@
         debug(info) printf( "name (%.*s)\n", cast(int) name.length, name.ptr );
         if( 'M' == tok() )
             next(); // has 'this' pointer
+		
+		if( addType )
         parseType( name );
     }
     
+	bool addType;
+	const(char)[] buf;
+	char[] dst;
+	
+char[] demangle( const(char)[] _buf, char[] _dst = null, bool _addType = true )
+{
+	buf = _buf;
+	dst = _dst;
+	addType = _addType;
+	
     while( true )
     {
         try
@@ -1251,7 +1263,7 @@
         }
         catch( ParseException e )
         {
-            debug
+            debug(info)
             {
                 auto msg = e.toString;
                 printf( "error: %.*s\n", cast(int) msg.length, msg.ptr );
@@ -1263,7 +1275,13 @@
         }
     }
 }
+}
 
+char[] demangle( const(char)[] buf, char[] dst = null, bool addType = true )
+{
+	Demangler dmngl;
+	return dmngl.demangle(buf, dst, addType);
+}
 
 unittest
 {
@@ -1276,8 +1294,8 @@
         [ "_D8demangle8demangleFAaZAa", "char[] demangle.demangle(char[])" ],
         [ "_D6object6Object8opEqualsFC6ObjectZi", "int object.Object.opEquals(class Object)" ],
         [ "_D4test2dgDFiYd", "double delegate(int, ...) test.dg" ],
-        //[ "_D4test58__T9factorialVde67666666666666860140VG5aa5_68656c6c6fVPvnZ9factorialf", "float test.factorial!(double 4.2, char[5] \"hello\"c, void* null).factorial" ],
-        //[ "_D4test101__T9factorialVde67666666666666860140Vrc9a999999999999d9014000000000000000c00040VG5aa5_68656c6c6fVPvnZ9factorialf", "float test.factorial!(double 4.2, cdouble 6.8+3i, char[5] \"hello\"c, void* null).factorial" ],
+        [ "_D4test58__T9factorialVde67666666666666860140VG5aa5_68656c6c6fVPvnZ9factorialf", "float test.factorial!(double 4.2, char[5] \"hello\"c, void* null).factorial" ],
+        [ "_D4test101__T9factorialVde67666666666666860140Vrc9a999999999999d9014000000000000000c00040VG5aa5_68656c6c6fVPvnZ9factorialf", "float test.factorial!(double 4.2, cdouble 6.8+3i, char[5] \"hello\"c, void* null).factorial" ],
         [ "_D4test34__T3barVG3uw3_616263VG3wd3_646566Z1xi", "int test.bar!(wchar[3] \"abc\"w, dchar[3] \"def\"d).x" ],
         [ "_D8demangle4testFLC6ObjectLDFLiZiZi", "int demangle.test(lazy class Object, lazy int delegate(lazy int))"],
         [ "_D8demangle4testFAiXi", "int demangle.test(int[] ...)"],
@@ -1298,3 +1316,46 @@
         */
     }
 }
+
+string decodeDmdString(char[] ln, ref int p)
+{
+	string s;
+	uint zlen, zpos;
+
+	// decompress symbol
+	while(p < ln.length)
+	{
+		int ch = cast(ubyte) ln[p++];
+		if ( (ch & 0xc0) == 0xc0 )
+		{
+			zlen = (ch & 0x7) + 1;
+			zpos = ((ch >> 3) & 7) + 1; // + zlen;
+			if ( zpos > s.length )
+				break;
+			s ~= s[$ - zpos .. $ - zpos + zlen];
+		}
+		else if ( ch >= 0x80 )
+		{
+			if ( p >= ln.length )
+				break;
+			int ch2 = cast(ubyte) ln[p++];
+			zlen = (ch2 & 0x7f) | ((ch & 0x38) << 4);
+			if ( p >= ln.length )
+				break;
+			int ch3 = cast(ubyte) ln[p++];
+			zpos = (ch3 & 0x7f) | ((ch & 7) << 7);
+			if ( zpos > s.length )
+				break;
+			s ~= s[$ - zpos .. $ - zpos + zlen];
+		}
+		else if( Demangler.isAlpha(cast(char)ch) || Demangler.isDigit(cast(char)ch) || ch == '_' )
+			s ~= cast(char) ch;
+		else
+		{
+			p--;
+			break;
+		}
+	}
+	return s;
+}
+
