Wolfgang Thallergcc 15.1.0ada185d1 year agoHistory
3224 lines · 93.9 KB · D
RawDownload
/** * The demangle module converts mangled D symbols to a representation similar * to what would have existed in code. * * Copyright: Copyright Sean Kelly 2010 - 2014. * License: Distributed under the *      $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). *    (See accompanying file LICENSE) * Authors:   Sean Kelly * Source:    $(DRUNTIMESRC core/_demangle.d) */ module core.demangle; version (OSX)    version = Darwin;else version (iOS)    version = Darwin;else version (TVOS)    version = Darwin;else version (WatchOS)    version = Darwin; debug (trace) debug = needPrintf;debug (info) debug = needPrintf; debug (needPrintf)private int printf(Args...)(scope const char* fmt, scope const Args args)    => __ctfe ? 0 : imported!"core.stdc.stdio".printf(fmt, args); extern (C) alias CXX_DEMANGLER = char* function (const char* mangled_name,                                                char* output_buffer,                                                size_t* length,                                                int* status) nothrow pure @trusted; private struct NoHooks{    // supported hooks    // static bool parseLName(ref Demangle);    // static char[] parseType(ref Demangle, char[])} private struct Demangle(Hooks = NoHooks){    // NOTE: This implementation currently only works with mangled function    //       names as they exist in an object file.  Type names mangled via    //       the .mangleof property are effectively incomplete as far as the    //       ABI is concerned and so are not considered to be mangled symbol    //       names.     // NOTE: This implementation builds the demangled buffer in place by    //       writing data as it is decoded and then rearranging it later as    //       needed.  In practice this results in very little data movement,    //       and the performance cost is more than offset by the gain from    //       not allocating dynamic memory to assemble the name piecemeal.    //    //       If the destination buffer is too small, parsing will restart    //       with a larger buffer.  Since this generally means only one    //       allocation during the course of a parsing run, this is still    //       faster than assembling the result piecemeal. pure @safe:    enum AddType { no, yes }      this( return scope const(char)[] buf_, return scope char[] dst_ = null )    {        this( buf_, AddType.yes, dst_ );    }      this( return scope const(char)[] buf_, AddType addType_, return scope char[] dst_ = null )    {        buf     = buf_;        addType = addType_;        dst.dst = dst_;    }     const(char)[]   buf     = null;    Buffer          dst;    size_t          pos     = 0;    size_t          brp     = 0; // current back reference pos    AddType         addType = AddType.yes;    bool            mute    = false;    Hooks           hooks;     //////////////////////////////////////////////////////////////////////////    // Type Testing and Conversion    //////////////////////////////////////////////////////////////////////////      static bool isAlpha( char val )    {        return ('a' <= val && 'z' >= val) ||               ('A' <= val && 'Z' >= val) ||               (0x80 & val); // treat all unicode as alphabetic    }      static bool isDigit( char val ) nothrow    {        return '0' <= val && '9' >= val;    }      static bool isHexDigit( char val )    {        return ('0' <= val && '9' >= val) ||               ('a' <= val && 'f' >= val) ||               ('A' <= val && 'F' >= val);    }      static ubyte ascii2hex( out bool errStatus, char val ) nothrow    {        if (val >= 'a' && val <= 'f')            return cast(ubyte)(val - 'a' + 10);        if (val >= 'A' && val <= 'F')            return cast(ubyte)(val - 'A' + 10);        if (val >= '0' && val <= '9')            return cast(ubyte)(val - '0');         errStatus = true;        return 0;    }     BufSlice shift(scope const BufSlice val) return scope    {        if (mute)            return dst.bslice_empty;        return dst.shift(val);    }     void putComma(size_t n)    {        version (DigitalMars) pragma(inline, false);        if (n)            put(", ");    }     void put(char c) return scope    {        char[1] val = c;        put(val[]);    }     void put(scope BufSlice val) return scope    {        put(val.getSlice);    }     void put(scope const(char)[] val) return scope nothrow    {        if (mute)            return;        dst.append(val);    }      void putAsHex( size_t val, int width = 0 )    {        import core.internal.string;         UnsignedStringBuf buf = void;         auto s = unsignedToTempString!16(val, buf);        int slen = cast(int)s.length;        if (slen < width)        {            foreach (i; slen .. width)                put('0');        }        put(s);    }      void pad( const(char)[] val )    {        if ( val.length )        {            put(" ");            put( val );        }    }      void silent( out bool err_status, void delegate(out bool err_status) pure @safe nothrow dg ) nothrow    {        debug(trace) printf( "silent+\n" );        debug(trace) scope(success) printf( "silent-\n" );        auto n = dst.length;        dg(err_status);        if(!err_status)            dst.len = n;    }      //////////////////////////////////////////////////////////////////////////    // Parsing Utility    //////////////////////////////////////////////////////////////////////////     @property bool empty()    {        return pos >= buf.length;    }     @property char front()    {        if ( pos < buf.length )            return buf[pos];        return char.init;    }     char peek( size_t n )    {        if ( pos + n < buf.length )            return buf[pos + n];        return char.init;    }      bool test( char val ) nothrow    {        return val == front;    }     void popFront() nothrow    {        if ( pos++ >= buf.length )            assert(false);    }      void popFront(int i) nothrow    {        while (i--)            popFront();    }      bool match( char val ) nothrow    {        if (!test(val))            return false;        else        {            popFront();            return true;        }    }     bool match( const(char)[] val ) nothrow    {        foreach (char e; val )            if (!match( e ))                return false;         return true;    }      void eat( char val )    {        if ( val == front )            popFront();    }     bool isSymbolNameFront(out bool errStatus) nothrow    {        char val = front;        if ( isDigit( val ) || val == '_' )            return true;        if ( val != 'Q' )            return false;         // check the back reference encoding after 'Q'        val = peekBackref();        if (val == 0)        {            // invalid back reference            errStatus = true;            return false;        }         return isDigit( val ); // identifier ref    }     // return the first character at the back reference    char peekBackref() nothrow    {        assert( front == 'Q' );        auto n = decodeBackref!1();        if (!n || n > pos)            return 0; // invalid back reference         return buf[pos - n];    }     size_t decodeBackref(size_t peekAt = 0)() nothrow    {        enum base = 26;        size_t n = 0;        for (size_t p; ; p++)        {            char t;            static if (peekAt > 0)            {                t = peek(peekAt + p);            }            else            {                t = front;                popFront();            }            if (t < 'A' || t > 'Z')            {                if (t < 'a' || t > 'z')                    return 0; // invalid back reference                 n = base * n + t - 'a';                return n;            }            n = base * n + t - 'A';        }    }     //////////////////////////////////////////////////////////////////////////    // Parsing Implementation    //////////////////////////////////////////////////////////////////////////      /*    Number:        Digit        Digit Number    */    const(char)[] sliceNumber() return scope    {        debug(trace) printf( "sliceNumber+\n" );        debug(trace) scope(success) printf( "sliceNumber-\n" );         auto beg = pos;         while ( true )        {            auto t = front;            if (t >= '0' && t <= '9')                popFront();            else                return buf[beg .. pos];        }    }      size_t decodeNumber(out bool errStatus) scope nothrow    {        debug(trace) printf( "decodeNumber+\n" );        debug(trace) scope(success) printf( "decodeNumber-\n" );         return decodeNumber( errStatus, sliceNumber() );    }     size_t decodeNumber( out bool errStatus, scope const(char)[] num ) scope nothrow    {        debug(trace) printf( "decodeNumber+\n" );        debug(trace) scope(success) printf( "decodeNumber-\n" );         size_t val = 0;         foreach ( c; num )        {            import core.checkedint : mulu, addu;             bool overflow = false;            val = mulu(val, 10, overflow);            val = addu(val, c - '0',  overflow);            if (overflow)            {                errStatus = true;                return 0;            }        }        return val;    }     void parseReal(out bool errStatus) scope nothrow    {        debug(trace) printf( "parseReal+\n" );        debug(trace) scope(success) printf( "parseReal-\n" );         char[64] tbuf = void;        size_t   tlen = 0;        real     val  = void;         void onError()        {            errStatus = true;        }         if ( 'I' == front )        {            if (!match("INF"))                return onError();            put( "real.infinity" );            return;        }        if ( 'N' == front )        {            popFront();            if ( 'I' == front )            {                if (!match("INF"))                    return onError();                put( "-real.infinity" );                return;            }            if ( 'A' == front )            {                if (!match("AN"))                    return onError();                put( "real.nan" );                return;            }            tbuf[tlen++] = '-';        }         tbuf[tlen++] = '0';        tbuf[tlen++] = 'X';        errStatus = !isHexDigit( front );        if (errStatus)            return; // Expected hex digit         tbuf[tlen++] = front;        tbuf[tlen++] = '.';        popFront();         while ( isHexDigit( front ) )        {            if (tlen >= tbuf.length)                return onError(); // Too many hex float digits            tbuf[tlen++] = front;            popFront();        }        if (!match('P'))            return onError();        tbuf[tlen++] = 'p';        if ( 'N' == front )        {            tbuf[tlen++] = '-';            popFront();        }        else        {            tbuf[tlen++] = '+';        }        while ( isDigit( front ) )        {            tbuf[tlen++] = front;            popFront();        }         tbuf[tlen] = 0;        debug(info) printf( "got (%s)\n", tbuf.ptr );        pureReprintReal( tbuf[] );        debug(info) printf( "converted (%.*s)\n", cast(int) tlen, tbuf.ptr );        put( tbuf[0 .. tlen] );    }      /*    LName:        Number Name     Name:        Namestart        Namestart Namechars     Namestart:        _        Alpha     Namechar:        Namestart        Digit     Namechars:        Namechar        Namechar Namechars    */    void parseLName(out string errMsg) scope nothrow    {        debug(trace) printf( "parseLName+\n" );        debug(trace) scope(success) printf( "parseLName-\n" );         static if (__traits(hasMember, Hooks, "parseLName"))        {            auto r = hooks.parseLName(errMsg, this);            if (errMsg !is null)                return;            if (r) return;

Lines 1–500 of 3224.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t