@@ -24,7 +24,14 @@ else version (WatchOS)
24
24
debug (trace) import core.stdc.stdio : printf;
25
25
debug (info) import core.stdc.stdio : printf;
26
26
27
- private struct Demangle
27
+ private struct NoHooks
28
+ {
29
+ // supported hooks
30
+ // static bool parseLName(ref Demangle);
31
+ // static char[] parseType(ref Demangle, char[])
32
+ }
33
+
34
+ private struct Demangle (Hooks = NoHooks)
28
35
{
29
36
// NOTE: This implementation currently only works with mangled function
30
37
// names as they exist in an object file. Type names mangled via
71
78
size_t brp = 0 ; // current back reference pos
72
79
AddType addType = AddType.yes;
73
80
bool mute = false ;
81
+ Hooks hooks;
74
82
75
83
static class ParseException : Exception
76
84
{
@@ -538,6 +546,10 @@ pure:
538
546
debug (trace) printf( " parseLName+\n " );
539
547
debug (trace) scope (success) printf( " parseLName-\n " );
540
548
549
+ static if (__traits(hasMember, Hooks, " parseLName" ))
550
+ if (hooks.parseLName(this ))
551
+ return ;
552
+
541
553
if ( front == ' Q' )
542
554
{
543
555
// back reference to LName
@@ -771,6 +783,10 @@ pure:
771
783
" dchar" , // w
772
784
];
773
785
786
+ static if (__traits(hasMember, Hooks, " parseType" ))
787
+ if (auto n = hooks.parseType(this , name))
788
+ return n;
789
+
774
790
debug (trace) printf( " parseType+\n " );
775
791
debug (trace) scope (success) printf( " parseType-\n " );
776
792
auto beg = len;
@@ -1962,7 +1978,7 @@ pure:
1962
1978
char [] demangle ( const (char )[] buf, char [] dst = null )
1963
1979
{
1964
1980
// return Demangle(buf, dst)();
1965
- auto d = Demangle(buf, dst);
1981
+ auto d = Demangle! () (buf, dst);
1966
1982
return d.demangleName();
1967
1983
}
1968
1984
@@ -1980,10 +1996,168 @@ char[] demangle( const(char)[] buf, char[] dst = null )
1980
1996
*/
1981
1997
char [] demangleType ( const (char )[] buf, char [] dst = null )
1982
1998
{
1983
- auto d = Demangle(buf, dst);
1999
+ auto d = Demangle! () (buf, dst);
1984
2000
return d.demangleType();
1985
2001
}
1986
2002
2003
+ /**
2004
+ * reencode a mangled symbol name that might include duplicate occurrences
2005
+ * of the same identifier by replacing all but the first occurence with
2006
+ * a back reference.
2007
+ *
2008
+ * Params:
2009
+ * mangled = The mangled string representing the type
2010
+ *
2011
+ * Returns:
2012
+ * The mangled name with deduplicated identifiers
2013
+ */
2014
+ char [] reencodeMangled (const (char )[] mangled) nothrow pure @safe
2015
+ {
2016
+ static struct PrependHooks
2017
+ {
2018
+ size_t lastpos;
2019
+ char [] result;
2020
+ size_t [const (char )[]] idpos; // identifier positions
2021
+
2022
+ static struct Replacement
2023
+ {
2024
+ size_t pos; // postion in original mangled string
2025
+ size_t respos; // postion in result string
2026
+ }
2027
+ Replacement [] replacements;
2028
+
2029
+ pure :
2030
+ size_t positionInResult (size_t pos)
2031
+ {
2032
+ foreach_reverse (r; replacements)
2033
+ if (pos >= r.pos)
2034
+ return r.respos + pos - r.pos;
2035
+ return pos;
2036
+ }
2037
+
2038
+ alias Remangle = Demangle! (PrependHooks);
2039
+
2040
+ bool parseLName (ref Remangle d)
2041
+ {
2042
+ if (lastpos < d.pos)
2043
+ result ~= d.buf[lastpos .. d.pos];
2044
+ else if (lastpos > d.pos)
2045
+ {
2046
+ // todo: roll back to earlier position
2047
+ }
2048
+
2049
+ auto reslen = result.length;
2050
+ auto refpos = d.pos;
2051
+ if (d.front == ' Q' )
2052
+ {
2053
+ size_t npos;
2054
+ {
2055
+ scope (exit) result.length = reslen; // remove all intermediate additions
2056
+ // only support identifier back references
2057
+ d.popFront();
2058
+ size_t n = d.decodeNumber! ' A' ();
2059
+ if (! n || n > refpos)
2060
+ d.error(" invalid back reference" );
2061
+
2062
+ auto savepos = d.pos;
2063
+ scope (exit) d.pos = savepos;
2064
+ size_t srcpos = refpos - n;
2065
+
2066
+ auto idlen = d.decodeNumber();
2067
+ if (d.pos + idlen > d.buf.length)
2068
+ d.error(" invalid back reference" );
2069
+ auto id = d.buf[d.pos .. d.pos + idlen];
2070
+ auto pid = id in idpos;
2071
+ if (! pid)
2072
+ d.error(" invalid back reference" );
2073
+ npos = positionInResult(* pid);
2074
+ }
2075
+ encodeBackref(reslen - npos, ' A' );
2076
+ replacements ~= Replacement(d.pos, result.length);
2077
+ }
2078
+ else
2079
+ {
2080
+ auto n = d.decodeNumber();
2081
+ if (! n || n > d.buf.length || n > d.buf.length - d.pos)
2082
+ d.error(" LName too shot or too long" );
2083
+ auto id = d.buf[d.pos .. d.pos + n];
2084
+ d.pos += n;
2085
+ if (auto pid = id in idpos)
2086
+ {
2087
+ size_t npos = positionInResult(* pid);
2088
+ result.length = reslen;
2089
+ encodeBackref(reslen - npos, ' A' );
2090
+ replacements ~= Replacement(d.pos, result.length);
2091
+ }
2092
+ else
2093
+ {
2094
+ idpos[id] = refpos;
2095
+ result ~= d.buf[refpos .. d.pos];
2096
+ }
2097
+ }
2098
+ lastpos = d.pos;
2099
+ return true ;
2100
+ }
2101
+
2102
+ char [] parseType ( ref Remangle d, char [] name = null )
2103
+ {
2104
+ if (d.front != ' Q' )
2105
+ return null ;
2106
+
2107
+ if (lastpos < d.pos)
2108
+ result ~= d.buf[lastpos .. d.pos];
2109
+ else if (lastpos > d.pos)
2110
+ {
2111
+ // todo: roll back to earlier position
2112
+ }
2113
+
2114
+ auto refPos = d.pos;
2115
+ d.popFront();
2116
+ auto n = d.decodeNumber! ' a' ();
2117
+ if (n == 0 || n > refPos)
2118
+ d.error(" invalid back reference" );
2119
+
2120
+ size_t npos = positionInResult(refPos - n);
2121
+ size_t reslen = result.length;
2122
+ encodeBackref(reslen - npos, ' a' );
2123
+
2124
+ lastpos = d.pos;
2125
+ return result[reslen .. $]; // anything but null
2126
+ }
2127
+
2128
+ void encodeBackref (size_t relpos, char lastDigitBase)
2129
+ {
2130
+ result ~= ' Q' ;
2131
+ size_t div = 1 ;
2132
+ while (relpos >= div * 10 )
2133
+ div *= 10 ;
2134
+ while (div >= 10 )
2135
+ {
2136
+ auto dig = (relpos / div);
2137
+ result ~= cast (char )(' 0' + dig);
2138
+ relpos -= dig * div;
2139
+ div /= 10 ;
2140
+ }
2141
+ result ~= cast (char )(lastDigitBase + relpos);
2142
+ }
2143
+ }
2144
+
2145
+ auto d = Demangle! (PrependHooks)(mangled, null );
2146
+ d.hooks = PrependHooks();
2147
+ d.mute = true ; // no demangled output
2148
+ try
2149
+ {
2150
+ () @trusted { d.parseMangledName(); }();
2151
+ if (d.hooks.lastpos < d.pos)
2152
+ d.hooks.result ~= d.buf[d.hooks.lastpos .. d.pos];
2153
+ return d.hooks.result;
2154
+ }
2155
+ catch (Exception )
2156
+ {
2157
+ // overflow exception cannot occur
2158
+ return mangled.dup ;
2159
+ }
2160
+ }
1987
2161
1988
2162
/**
1989
2163
* Mangles a D symbol.
@@ -2045,7 +2219,11 @@ char[] mangle(T)(const(char)[] fqn, char[] dst = null) @safe pure nothrow
2045
2219
}
2046
2220
dst[i .. i + T.mangleof.length] = T.mangleof[];
2047
2221
i += T.mangleof.length;
2048
- return dst[0 .. i];
2222
+
2223
+ static if (hasTypeBackRef)
2224
+ return reencodeMangled (dst[0 .. i]);
2225
+ else
2226
+ return dst[0 .. i];
2049
2227
}
2050
2228
2051
2229
@@ -2105,12 +2283,19 @@ char[] mangleFunc(T:FT*, FT)(const(char)[] fqn, char[] dst = null) @safe pure no
2105
2283
}
2106
2284
}
2107
2285
2286
+ private enum hasTypeBackRef = (int function (void ** ,void ** )).mangleof[$- 4 .. $] == " QdZi" ;
2108
2287
2109
2288
// /
2110
2289
unittest
2111
2290
{
2112
2291
assert (mangleFunc! (int function (int ))(" a.b" ) == " _D1a1bFiZi" );
2113
- assert (mangleFunc! (int function (Object ))(" object.Object.opEquals" ) == " _D6object6Object8opEqualsFC6ObjectZi" );
2292
+ static if (hasTypeBackRef)
2293
+ {
2294
+ assert (mangleFunc! (int function (Object ))(" object.Object.opEquals" ) == " _D6object6Object8opEqualsFCQ1IZi" );
2295
+ assert (mangleFunc! (int function (Object , Object ))(" object.Object.opEquals" ) == " _D6object6Object8opEqualsFCQ1IQeZi" );
2296
+ }
2297
+ else
2298
+ assert (mangleFunc! (int function (Object ))(" object.Object.opEquals" ) == " _D6object6Object8opEqualsFC6ObjectZi" );
2114
2299
}
2115
2300
2116
2301
unittest
@@ -2343,7 +2528,7 @@ string decodeDmdString( const(char)[] ln, ref size_t p )
2343
2528
break ;
2344
2529
s ~= s[$ - zpos .. $ - zpos + zlen];
2345
2530
}
2346
- else if ( Demangle.isAlpha(cast (char )ch) || Demangle.isDigit(cast (char )ch) || ch == ' _' )
2531
+ else if ( Demangle! () .isAlpha(cast (char )ch) || Demangle! () .isDigit(cast (char )ch) || ch == ' _' )
2347
2532
s ~= cast (char ) ch;
2348
2533
else
2349
2534
{
0 commit comments