Annotation of GNUtools/c++filt/cplus-dem.c, revision 1.1.1.1

1.1       root        1: /* Demangler for GNU C++ 
                      2:    Copyright 1989, 1991 Free Software Foundation, Inc.
                      3:    Written by James Clark ([email protected])
                      4:    Rewritten by Fred Fish ([email protected]) for ARM and Lucid demangling
                      5:    
                      6: This file is part of the libiberty library.
                      7: Libiberty is free software; you can redistribute it and/or
                      8: modify it under the terms of the GNU Library General Public
                      9: License as published by the Free Software Foundation; either
                     10: version 2 of the License, or (at your option) any later version.
                     11: 
                     12: Libiberty is distributed in the hope that it will be useful,
                     13: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     15: Library General Public License for more details.
                     16: 
                     17: You should have received a copy of the GNU Library General Public
                     18: License along with libiberty; see the file COPYING.LIB.  If
                     19: not, write to the Free Software Foundation, Inc., 675 Mass Ave,
                     20: Cambridge, MA 02139, USA.  */
                     21: 
                     22: /* This file exports two functions; cplus_mangle_opname and cplus_demangle.
                     23: 
                     24:    This file imports xmalloc and xrealloc, which are like malloc and
                     25:    realloc except that they generate a fatal error if there is no
                     26:    available memory. */
                     27: 
                     28: #include "demangle.h"
                     29: #undef CURRENT_DEMANGLING_STYLE
                     30: #define CURRENT_DEMANGLING_STYLE work->options
                     31: #include <ctype.h>
                     32: #include <string.h>
                     33: #include <stdio.h>
                     34: 
                     35: extern char *xmalloc PARAMS((long));
                     36: extern char *xrealloc PARAMS((PTR, long));
                     37: extern char *strstr PARAMS ((const char *, const char *));
                     38: extern void free PARAMS((PTR));
                     39: 
                     40: /* In order to allow a single demangler executable to demangle strings
                     41:    using various common values of CPLUS_MARKER, as well as any specific
                     42:    one set at compile time, we maintain a string containing all the
                     43:    commonly used ones, and check to see if the marker we are looking for
                     44:    is in that string.  CPLUS_MARKER is usually '$' on systems where the
                     45:    assembler can deal with that.  Where the assembler can't, it's usually
                     46:    '.' (but on many systems '.' is used for other things).  We put the
                     47:    current defined CPLUS_MARKER first (which defaults to '$'), followed
                     48:    by the next most common value, followed by an explicit '$' in case
                     49:    the value of CPLUS_MARKER is not '$'.
                     50: 
                     51:    We could avoid this if we could just get g++ to tell us what the actual
                     52:    cplus marker character is as part of the debug information, perhaps by
                     53:    ensuring that it is the character that terminates the gcc<n>_compiled
                     54:    marker symbol (FIXME). */
                     55: 
                     56: #if !defined (CPLUS_MARKER)
                     57: #define CPLUS_MARKER '$'
                     58: #endif
                     59: 
                     60: enum demangling_styles current_demangling_style = gnu_demangling;
                     61: 
                     62: static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
                     63: 
                     64: void
                     65: set_cplus_marker_for_demangling (ch)
                     66:      int ch;
                     67: {
                     68:     cplus_markers[0] = ch;
                     69: }
                     70: 
                     71: /* Stuff that is shared between sub-routines.
                     72:  * Using a shared structure allows cplus_demangle to be reentrant. */
                     73: 
                     74: struct work_stuff
                     75: {
                     76:   int options;
                     77:   char **typevec;
                     78:   int ntypes;
                     79:   int typevec_size;
                     80:   int constructor;
                     81:   int destructor;
                     82:   int static_type;     /* A static member function */
                     83:   int const_type;      /* A const member function */
                     84: };
                     85: 
                     86: #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
                     87: #define PRINT_ARG_TYPES       (work -> options & DMGL_PARAMS)
                     88: 
                     89: static CONST struct optable
                     90: {
                     91:   CONST char *in;
                     92:   CONST char *out;
                     93:   int flags;
                     94: } optable[] = {
                     95:   {"nw",         " new",       DMGL_ANSI},     /* new (1.92,    ansi) */
                     96:   {"dl",         " delete",    DMGL_ANSI},     /* new (1.92,    ansi) */
                     97:   {"new",        " new",       0},             /* old (1.91,    and 1.x) */
                     98:   {"delete",     " delete",    0},             /* old (1.91,    and 1.x) */
                     99:   {"as",         "=",          DMGL_ANSI},     /* ansi */
                    100:   {"ne",         "!=",         DMGL_ANSI},     /* old, ansi */
                    101:   {"eq",         "==",         DMGL_ANSI},     /* old, ansi */
                    102:   {"ge",         ">=",         DMGL_ANSI},     /* old, ansi */
                    103:   {"gt",         ">",          DMGL_ANSI},     /* old, ansi */
                    104:   {"le",         "<=",         DMGL_ANSI},     /* old, ansi */
                    105:   {"lt",         "<",          DMGL_ANSI},     /* old, ansi */
                    106:   {"plus",       "+",          0},             /* old */
                    107:   {"pl",         "+",          DMGL_ANSI},     /* ansi */
                    108:   {"apl",        "+=",         DMGL_ANSI},     /* ansi */
                    109:   {"minus",      "-",          0},             /* old */
                    110:   {"mi",         "-",          DMGL_ANSI},     /* ansi */
                    111:   {"ami",        "-=",         DMGL_ANSI},     /* ansi */
                    112:   {"mult",       "*",          0},             /* old */
                    113:   {"ml",         "*",          DMGL_ANSI},     /* ansi */
                    114:   {"amu",        "*=",         DMGL_ANSI},     /* ansi (ARM/Lucid) */
                    115:   {"aml",        "*=",         DMGL_ANSI},     /* ansi (GNU/g++) */
                    116:   {"convert",    "+",          0},             /* old (unary +) */
                    117:   {"negate",     "-",          0},             /* old (unary -) */
                    118:   {"trunc_mod",          "%",          0},             /* old */
                    119:   {"md",         "%",          DMGL_ANSI},     /* ansi */
                    120:   {"amd",        "%=",         DMGL_ANSI},     /* ansi */
                    121:   {"trunc_div",          "/",          0},             /* old */
                    122:   {"dv",         "/",          DMGL_ANSI},     /* ansi */
                    123:   {"adv",        "/=",         DMGL_ANSI},     /* ansi */
                    124:   {"truth_andif", "&&",                0},             /* old */
                    125:   {"aa",         "&&",         DMGL_ANSI},     /* ansi */
                    126:   {"truth_orif",  "||",                0},             /* old */
                    127:   {"oo",         "||",         DMGL_ANSI},     /* ansi */
                    128:   {"truth_not",          "!",          0},             /* old */
                    129:   {"nt",         "!",          DMGL_ANSI},     /* ansi */
                    130:   {"postincrement","++",       0},             /* old */
                    131:   {"pp",         "++",         DMGL_ANSI},     /* ansi */
                    132:   {"postdecrement","--",       0},             /* old */
                    133:   {"mm",         "--",         DMGL_ANSI},     /* ansi */
                    134:   {"bit_ior",    "|",          0},             /* old */
                    135:   {"or",         "|",          DMGL_ANSI},     /* ansi */
                    136:   {"aor",        "|=",         DMGL_ANSI},     /* ansi */
                    137:   {"bit_xor",    "^",          0},             /* old */
                    138:   {"er",         "^",          DMGL_ANSI},     /* ansi */
                    139:   {"aer",        "^=",         DMGL_ANSI},     /* ansi */
                    140:   {"bit_and",    "&",          0},             /* old */
                    141:   {"ad",         "&",          DMGL_ANSI},     /* ansi */
                    142:   {"aad",        "&=",         DMGL_ANSI},     /* ansi */
                    143:   {"bit_not",    "~",          0},             /* old */
                    144:   {"co",         "~",          DMGL_ANSI},     /* ansi */
                    145:   {"call",       "()",         0},             /* old */
                    146:   {"cl",         "()",         DMGL_ANSI},     /* ansi */
                    147:   {"alshift",    "<<",         0},             /* old */
                    148:   {"ls",         "<<",         DMGL_ANSI},     /* ansi */
                    149:   {"als",        "<<=",        DMGL_ANSI},     /* ansi */
                    150:   {"arshift",    ">>",         0},             /* old */
                    151:   {"rs",         ">>",         DMGL_ANSI},     /* ansi */
                    152:   {"ars",        ">>=",        DMGL_ANSI},     /* ansi */
                    153:   {"component",          "->",         0},             /* old */
                    154:   {"pt",         "->",         DMGL_ANSI},     /* ansi; Lucid C++ form */
                    155:   {"rf",         "->",         DMGL_ANSI},     /* ansi; ARM/GNU form */
                    156:   {"indirect",   "*",          0},             /* old */
                    157:   {"method_call",  "->()",     0},             /* old */
                    158:   {"addr",       "&",          0},             /* old (unary &) */
                    159:   {"array",      "[]",         0},             /* old */
                    160:   {"vc",         "[]",         DMGL_ANSI},     /* ansi */
                    161:   {"compound",   ", ",         0},             /* old */
                    162:   {"cm",         ", ",         DMGL_ANSI},     /* ansi */
                    163:   {"cond",       "?:",         0},             /* old */
                    164:   {"cn",         "?:",         DMGL_ANSI},     /* psuedo-ansi */
                    165:   {"max",        ">?",         0},             /* old */
                    166:   {"mx",         ">?",         DMGL_ANSI},     /* psuedo-ansi */
                    167:   {"min",        "<?",         0},             /* old */
                    168:   {"mn",         "<?",         DMGL_ANSI},     /* psuedo-ansi */
                    169:   {"nop",        "",           0},             /* old (for operator=) */
                    170:   {"rm",         "->*",        DMGL_ANSI}      /* ansi */
                    171: };
                    172: 
                    173: 
                    174: typedef struct string          /* Beware: these aren't required to be */
                    175: {                              /*  '\0' terminated. */
                    176:   char *b;                     /* pointer to start of string */
                    177:   char *p;                     /* pointer after last character */
                    178:   char *e;                     /* pointer after end of allocated space */
                    179: } string;
                    180: 
                    181: #define STRING_EMPTY(str)      ((str) -> b == (str) -> p)
                    182: #define PREPEND_BLANK(str)     {if (!STRING_EMPTY(str)) \
                    183:                                   string_prepend(str, " ");}
                    184: #define APPEND_BLANK(str)      {if (!STRING_EMPTY(str)) \
                    185:                                   string_append(str, " ");}
                    186: 
                    187: #define ARM_VTABLE_STRING "__vtbl__"   /* Lucid/ARM virtual table prefix */
                    188: #define ARM_VTABLE_STRLEN 8            /* strlen (ARM_VTABLE_STRING) */
                    189: 
                    190: /* Prototypes for local functions */
                    191: 
                    192: static char *
                    193: mop_up PARAMS ((struct work_stuff *, string *, int));
                    194: 
                    195: #if 0
                    196: static int
                    197: demangle_method_args PARAMS ((struct work_stuff *work, CONST char **, string *));
                    198: #endif
                    199: 
                    200: static int
                    201: demangle_template PARAMS ((struct work_stuff *work, CONST char **, string *,
                    202:                           string *));
                    203: 
                    204: static int
                    205: demangle_qualified PARAMS ((struct work_stuff *, CONST char **, string *,
                    206:                            int, int));
                    207: 
                    208: static int
                    209: demangle_class PARAMS ((struct work_stuff *, CONST char **, string *));
                    210: 
                    211: static int
                    212: demangle_fund_type PARAMS ((struct work_stuff *, CONST char **, string *));
                    213: 
                    214: static int
                    215: demangle_signature PARAMS ((struct work_stuff *, CONST char **, string *));
                    216: 
                    217: static int
                    218: demangle_prefix PARAMS ((struct work_stuff *, CONST char **, string *));
                    219: 
                    220: static int
                    221: gnu_special PARAMS ((struct work_stuff *, CONST char **, string *));
                    222: 
                    223: static int
                    224: arm_special PARAMS ((struct work_stuff *, CONST char **, string *));
                    225: 
                    226: static void
                    227: string_need PARAMS ((string *, int));
                    228: 
                    229: static void
                    230: string_delete PARAMS ((string *));
                    231: 
                    232: static void
                    233: string_init PARAMS ((string *));
                    234: 
                    235: static void
                    236: string_clear PARAMS ((string *));
                    237: 
                    238: #if 0
                    239: static int
                    240: string_empty PARAMS ((string *));
                    241: #endif
                    242: 
                    243: static void
                    244: string_append PARAMS ((string *, CONST char *));
                    245: 
                    246: static void
                    247: string_appends PARAMS ((string *, string *));
                    248: 
                    249: static void
                    250: string_appendn PARAMS ((string *, CONST char *, int));
                    251: 
                    252: static void
                    253: string_prepend PARAMS ((string *, CONST char *));
                    254: 
                    255: static void
                    256: string_prependn PARAMS ((string *, CONST char *, int));
                    257: 
                    258: static int
                    259: get_count PARAMS ((CONST char **, int *));
                    260: 
                    261: static int
                    262: consume_count PARAMS ((CONST char **));
                    263: 
                    264: static int
                    265: demangle_args PARAMS ((struct work_stuff *, CONST char **, string *));
                    266: 
                    267: static int
                    268: do_type PARAMS ((struct work_stuff *, CONST char **, string *));
                    269: 
                    270: static int
                    271: do_arg PARAMS ((struct work_stuff *, CONST char **, string *));
                    272: 
                    273: static void
                    274: demangle_function_name PARAMS ((struct work_stuff *, CONST char **, string *,
                    275:                                CONST char *));
                    276: 
                    277: static void
                    278: remember_type PARAMS ((struct work_stuff *, CONST char *, int));
                    279: 
                    280: static void
                    281: forget_types PARAMS ((struct work_stuff *));
                    282: 
                    283: static void
                    284: string_prepends PARAMS ((string *, string *));
                    285: 
                    286: /*  Translate count to integer, consuming tokens in the process.
                    287:     Conversion terminates on the first non-digit character.
                    288:     Trying to consume something that isn't a count results in
                    289:     no consumption of input and a return of 0. */
                    290: 
                    291: static int
                    292: consume_count (type)
                    293:     CONST char **type;
                    294: {
                    295:     int count = 0;
                    296: 
                    297:     while (isdigit (**type))
                    298:       {
                    299:        count *= 10;
                    300:        count += **type - '0';
                    301:        (*type)++;
                    302:       }
                    303:     return (count);
                    304: }
                    305: 
                    306: /* Takes operator name as e.g. "++" and returns mangled
                    307:    operator name (e.g. "postincrement_expr"), or NULL if not found.
                    308: 
                    309:    If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
                    310:    if OPTIONS & DMGL_ANSI == 0, return the old GNU name.  */
                    311: 
                    312: char *
                    313: cplus_mangle_opname (opname, options)
                    314:      char *opname;
                    315:      int options;
                    316: {
                    317:   int i;
                    318:   int len;
                    319: 
                    320:   len = strlen (opname);
                    321:   for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
                    322:     {
                    323:       if (strlen (optable[i].out) == len
                    324:          && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
                    325:          && memcmp (optable[i].out, opname, len) == 0)
                    326:        return ((char *)optable[i].in);
                    327:     }
                    328:   return (0);
                    329: }
                    330: 
                    331: /* check to see whether MANGLED can match TEXT in the first TEXT_LEN
                    332:    characters. */
                    333: 
                    334: int cplus_match (mangled, text, text_len)
                    335:      CONST char *mangled;
                    336:      char *text;
                    337:      int text_len;
                    338: {
                    339:   if (strncmp (mangled, text, text_len) != 0) {
                    340:     return(0); /* cannot match either */
                    341:   } else {
                    342:     return(1); /* matches mangled, may match demangled */
                    343:   }
                    344: }
                    345: 
                    346: /* char *cplus_demangle (const char *mangled, int options)
                    347: 
                    348:    If MANGLED is a mangled function name produced by GNU C++, then
                    349:    a pointer to a malloced string giving a C++ representation
                    350:    of the name will be returned; otherwise NULL will be returned.
                    351:    It is the caller's responsibility to free the string which
                    352:    is returned.
                    353: 
                    354:    The OPTIONS arg may contain one or more of the following bits:
                    355: 
                    356:        DMGL_ANSI       ANSI qualifiers such as `const' and `void' are
                    357:                        included.
                    358:        DMGL_PARAMS     Function parameters are included.
                    359: 
                    360:    For example,
                    361:    
                    362:    cplus_demangle ("foo__1Ai", DMGL_PARAMS)            => "A::foo(int)"
                    363:    cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI)        => "A::foo(int)"
                    364:    cplus_demangle ("foo__1Ai", 0)                      => "A::foo"
                    365: 
                    366:    cplus_demangle ("foo__1Afe", DMGL_PARAMS)           => "A::foo(float,...)"
                    367:    cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
                    368:    cplus_demangle ("foo__1Afe", 0)                     => "A::foo"
                    369: 
                    370:    Note that any leading underscores, or other such characters prepended by
                    371:    the compilation system, are presumed to have already been stripped from
                    372:    MANGLED.  */
                    373: 
                    374: char *
                    375: cplus_demangle (mangled, options)
                    376:      CONST char *mangled;
                    377:      int options;
                    378: {
                    379:   string decl;
                    380:   int success = 0;
                    381:   struct work_stuff work[1];
                    382:   char *demangled = NULL;
                    383: 
                    384:   if ((mangled != NULL) && (*mangled != '\0'))
                    385:     {
                    386:       memset ((char *) work, 0, sizeof (work));
                    387:       work -> options = options;
                    388:       if ((work->options & DMGL_STYLE_MASK) == 0)
                    389:        work->options |= (int)current_demangling_style & DMGL_STYLE_MASK;
                    390:       
                    391:       string_init (&decl);
                    392: 
                    393:       /* First check to see if gnu style demangling is active and if the
                    394:         string to be demangled contains a CPLUS_MARKER.  If so, attempt to
                    395:         recognize one of the gnu special forms rather than looking for a
                    396:         standard prefix.  In particular, don't worry about whether there
                    397:         is a "__" string in the mangled string.  Consider "_$_5__foo" for
                    398:         example. */
                    399: 
                    400:       if ((AUTO_DEMANGLING || GNU_DEMANGLING))
                    401:        {
                    402:          success = gnu_special (work, &mangled, &decl);
                    403:        }
                    404:       if (!success)
                    405:        {
                    406:          success = demangle_prefix (work, &mangled, &decl);
                    407:        }
                    408:       if (success && (*mangled != '\0'))
                    409:        {
                    410:          success = demangle_signature (work, &mangled, &decl);
                    411:        }
                    412:       if (work->constructor == 2)
                    413:         {
                    414:           string_prepend(&decl, "global constructors keyed to ");
                    415:           work->constructor = 0;
                    416:         }
                    417:       else if (work->destructor == 2)
                    418:         {
                    419:           string_prepend(&decl, "global destructors keyed to ");
                    420:           work->destructor = 0;
                    421:         }
                    422:       demangled = mop_up (work, &decl, success);
                    423:     }
                    424:   return (demangled);
                    425: }
                    426: 
                    427: static char *
                    428: mop_up (work, declp, success)
                    429:      struct work_stuff *work;
                    430:      string *declp;
                    431:      int success;
                    432: {
                    433:   char *demangled = NULL;
                    434: 
                    435:   /* Discard the remembered types, if any. */
                    436:   
                    437:   forget_types (work);
                    438:   if (work -> typevec != NULL)
                    439:     {
                    440:       free ((char *) work -> typevec);
                    441:     }
                    442:   
                    443:   /* If demangling was successful, ensure that the demangled string is null
                    444:      terminated and return it.  Otherwise, free the demangling decl. */
                    445:   
                    446:   if (!success)
                    447:     {
                    448:       string_delete (declp);
                    449:     }
                    450:   else
                    451:     {
                    452:       string_appendn (declp, "", 1);
                    453:       demangled = declp -> b;
                    454:     }
                    455:   return (demangled);
                    456: }
                    457: 
                    458: /*
                    459: 
                    460: LOCAL FUNCTION
                    461: 
                    462:        demangle_signature -- demangle the signature part of a mangled name
                    463: 
                    464: SYNOPSIS
                    465: 
                    466:        static int
                    467:        demangle_signature (struct work_stuff *work, const char **mangled,
                    468:                            string *declp);
                    469: 
                    470: DESCRIPTION
                    471: 
                    472:        Consume and demangle the signature portion of the mangled name.
                    473: 
                    474:        DECLP is the string where demangled output is being built.  At
                    475:        entry it contains the demangled root name from the mangled name
                    476:        prefix.  I.E. either a demangled operator name or the root function
                    477:        name.  In some special cases, it may contain nothing.
                    478: 
                    479:        *MANGLED points to the current unconsumed location in the mangled
                    480:        name.  As tokens are consumed and demangling is performed, the
                    481:        pointer is updated to continuously point at the next token to
                    482:        be consumed.
                    483: 
                    484:        Demangling GNU style mangled names is nasty because there is no
                    485:        explicit token that marks the start of the outermost function
                    486:        argument list.
                    487: */
                    488: 
                    489: static int
                    490: demangle_signature (work, mangled, declp)
                    491:      struct work_stuff *work;
                    492:      CONST char **mangled;
                    493:      string *declp;
                    494: {
                    495:   int success = 1;
                    496:   int func_done = 0;
                    497:   int expect_func = 0;
                    498:   CONST char *oldmangled = NULL;
                    499:   string trawname;
                    500:   string tname;
                    501: 
                    502:   while (success && (**mangled != '\0'))
                    503:     {
                    504:       switch (**mangled)
                    505:        {
                    506:          case 'Q':
                    507:            oldmangled = *mangled;
                    508:            success = demangle_qualified (work, mangled, declp, 1, 0);
                    509:            if (success)
                    510:              {
                    511:                remember_type (work, oldmangled, *mangled - oldmangled);
                    512:              }
                    513:            if (AUTO_DEMANGLING || GNU_DEMANGLING)
                    514:              {
                    515:                expect_func = 1;
                    516:              }
                    517:            oldmangled = NULL;
                    518:            break;
                    519:          
                    520:          case 'S':
                    521:            /* Static member function */
                    522:            if (oldmangled == NULL)
                    523:              {
                    524:                oldmangled = *mangled;
                    525:              }
                    526:            (*mangled)++;
                    527:            work -> static_type = 1;
                    528:            break;
                    529: 
                    530:          case 'C':
                    531:            /* a const member function */
                    532:            if (oldmangled == NULL)
                    533:              {
                    534:                oldmangled = *mangled;
                    535:              }
                    536:            (*mangled)++;
                    537:            work -> const_type = 1;
                    538:            break;
                    539:          
                    540:          case '0': case '1': case '2': case '3': case '4':
                    541:          case '5': case '6': case '7': case '8': case '9':
                    542:            if (oldmangled == NULL)
                    543:              {
                    544:                oldmangled = *mangled;
                    545:              }
                    546:            success = demangle_class (work, mangled, declp);
                    547:            if (success)
                    548:              {
                    549:                remember_type (work, oldmangled, *mangled - oldmangled);
                    550:              }
                    551:            if (AUTO_DEMANGLING || GNU_DEMANGLING)
                    552:              {
                    553:                expect_func = 1;
                    554:              }
                    555:            oldmangled = NULL;
                    556:            break;
                    557:          
                    558:          case 'F':
                    559:            /* Function */
                    560:            /* ARM style demangling includes a specific 'F' character after
                    561:             the class name.  For GNU style, it is just implied.  So we can
                    562:             safely just consume any 'F' at this point and be compatible
                    563:             with either style. */
                    564: 
                    565:            oldmangled = NULL;
                    566:            func_done = 1;
                    567:            (*mangled)++;
                    568: 
                    569:            /* For lucid/ARM style we have to forget any types we might
                    570:               have remembered up to this point, since they were not argument
                    571:               types.  GNU style considers all types seen as available for
                    572:               back references.  See comment in demangle_args() */
                    573: 
                    574:            if (LUCID_DEMANGLING || ARM_DEMANGLING)
                    575:              {
                    576:                forget_types (work);
                    577:              }
                    578:            success = demangle_args (work, mangled, declp);
                    579:            break;
                    580:          
                    581:          case 't':
                    582:            /* G++ Template */
                    583:            string_init(&trawname); 
                    584:            string_init(&tname);
                    585:            success = demangle_template (work, mangled, &tname, &trawname);
                    586:            string_append(&tname, "::");
                    587:            string_prepends(declp, &tname);
                    588:            if (work -> destructor & 1)
                    589:              {
                    590:                string_prepend (&trawname, "~");
                    591:                string_appends (declp, &trawname);
                    592:                work->destructor -= 1;
                    593:              }
                    594:            if ((work->constructor & 1) || (work->destructor & 1))
                    595:              {
                    596:                string_appends (declp, &trawname);
                    597:                work->constructor -= 1;
                    598:               }
                    599:            string_delete(&trawname);
                    600:            string_delete(&tname);
                    601:            expect_func = 1;
                    602:            break;
                    603: 
                    604:          case '_':
                    605:            /* At the outermost level, we cannot have a return type specified,
                    606:               so if we run into another '_' at this point we are dealing with
                    607:               a mangled name that is either bogus, or has been mangled by
                    608:               some algorithm we don't know how to deal with.  So just
                    609:               reject the entire demangling. */
                    610:            success = 0;
                    611:            break;
                    612: 
                    613:          default:
                    614:            if (AUTO_DEMANGLING || GNU_DEMANGLING)
                    615:              {
                    616:                /* Assume we have stumbled onto the first outermost function
                    617:                   argument token, and start processing args. */
                    618:                func_done = 1;
                    619:                success = demangle_args (work, mangled, declp);
                    620:              }
                    621:            else
                    622:              {
                    623:                /* Non-GNU demanglers use a specific token to mark the start
                    624:                   of the outermost function argument tokens.  Typically 'F',
                    625:                   for ARM-demangling, for example.  So if we find something
                    626:                   we are not prepared for, it must be an error. */
                    627:                success = 0;
                    628:              }
                    629:            break;
                    630:        }
                    631:       if (AUTO_DEMANGLING || GNU_DEMANGLING)
                    632:        {
                    633:          if (success && expect_func)
                    634:            {
                    635:              func_done = 1;
                    636:              success = demangle_args (work, mangled, declp);
                    637:            }
                    638:        }
                    639:     }
                    640:   if (success && !func_done)
                    641:     {
                    642:       if (AUTO_DEMANGLING || GNU_DEMANGLING)
                    643:        {
                    644:          /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
                    645:             bar__3fooi is 'foo::bar(int)'.  We get here when we find the
                    646:             first case, and need to ensure that the '(void)' gets added to
                    647:             the current declp.  Note that with ARM, the first case
                    648:             represents the name of a static data member 'foo::bar',
                    649:             which is in the current declp, so we leave it alone. */
                    650:          success = demangle_args (work, mangled, declp);
                    651:        }
                    652:     }
                    653:   if (success && work -> static_type && PRINT_ARG_TYPES)
                    654:     {
                    655:       string_append (declp, " static");
                    656:     }
                    657:   if (success && work -> const_type && PRINT_ARG_TYPES)
                    658:     {
                    659:       string_append (declp, " const");
                    660:     }
                    661:   return (success);
                    662: }
                    663: 
                    664: #if 0
                    665: 
                    666: static int
                    667: demangle_method_args (work, mangled, declp)
                    668:      struct work_stuff *work;
                    669:      CONST char **mangled;
                    670:      string *declp;
                    671: {
                    672:   int success = 0;
                    673: 
                    674:   if (work -> static_type)
                    675:     {
                    676:       string_append (declp, *mangled + 1);
                    677:       *mangled += strlen (*mangled);
                    678:       success = 1;
                    679:     }
                    680:   else
                    681:     {
                    682:       success = demangle_args (work, mangled, declp);
                    683:     }
                    684:   return (success);
                    685: }
                    686: 
                    687: #endif
                    688: 
                    689: static int
                    690: demangle_template (work, mangled, tname, trawname)
                    691:      struct work_stuff *work;
                    692:      CONST char **mangled;
                    693:      string *tname;
                    694:      string *trawname;
                    695: {
                    696:   int i;
                    697:   int is_pointer;
                    698:   int is_real;
                    699:   int is_integral;
                    700:   int r;
                    701:   int need_comma = 0;
                    702:   int success = 0;
                    703:   int done;
                    704:   CONST char *old_p;
                    705:   CONST char *start;
                    706:   int symbol_len;
                    707:   string temp;
                    708: 
                    709:   (*mangled)++;
                    710:   start = *mangled;
                    711:   /* get template name */
                    712:   if ((r = consume_count (mangled)) == 0)
                    713:     {
                    714:       return (0);
                    715:     }
                    716:   if (trawname)
                    717:     string_appendn (trawname, *mangled, r);
                    718:   string_appendn (tname, *mangled, r);
                    719:   *mangled += r;
                    720:   string_append (tname, "<");
                    721:   /* get size of template parameter list */
                    722:   if (!get_count (mangled, &r))
                    723:     {
                    724:       return (0);
                    725:     }
                    726:   for (i = 0; i < r; i++)
                    727:     {
                    728:       if (need_comma)
                    729:        {
                    730:          string_append (tname, ", ");
                    731:        }
                    732:       /* Z for type parameters */
                    733:       if (**mangled == 'Z')
                    734:        {
                    735:          (*mangled)++;
                    736:          /* temp is initialized in do_type */
                    737:          success = do_type (work, mangled, &temp);
                    738:          if (success)
                    739:            {
                    740:              string_appends (tname, &temp);
                    741:            }
                    742:          string_delete(&temp);
                    743:          if (!success)
                    744:            {
                    745:              break;
                    746:            }
                    747:        }
                    748:       else
                    749:        {
                    750:          /* otherwise, value parameter */
                    751:          old_p  = *mangled;
                    752:          is_pointer = 0;
                    753:          is_real = 0;
                    754:          is_integral = 0;
                    755:          done = 0;
                    756:          /* temp is initialized in do_type */
                    757:          success = do_type (work, mangled, &temp);
                    758:          if (success)
                    759:            {
                    760:              string_appends (tname, &temp);
                    761:            }
                    762:          string_delete(&temp);
                    763:          if (!success)
                    764:            {
                    765:              break;
                    766:            }
                    767:          string_append (tname, "=");
                    768:          while (*old_p && !done)
                    769:            {   
                    770:              switch (*old_p)
                    771:                {
                    772:                  case 'P':
                    773:                  case 'R':
                    774:                    done = is_pointer = 1;
                    775:                    break;
                    776:                  case 'C':     /* const */
                    777:                  case 'S':     /* explicitly signed [char] */
                    778:                  case 'U':     /* unsigned */
                    779:                  case 'V':     /* volatile */
                    780:                  case 'F':     /* function */
                    781:                  case 'M':     /* member function */
                    782:                  case 'O':     /* ??? */
                    783:                    old_p++;
                    784:                    continue;
                    785:                  case 'Q':     /* repetition of following */
                    786:                  case 'T':     /* remembered type */
                    787:                    abort ();
                    788:                    break;
                    789:                  case 'v':     /* void */
                    790:                    abort ();
                    791:                    break;
                    792:                  case 'x':     /* long long */
                    793:                  case 'l':     /* long */
                    794:                  case 'i':     /* int */
                    795:                  case 's':     /* short */
                    796:                  case 'c':     /* char */
                    797:                  case 'w':     /* wchar_t */
                    798:                    done = is_integral = 1;
                    799:                    break;
                    800:                  case 'r':     /* long double */
                    801:                  case 'd':     /* double */
                    802:                  case 'f':     /* float */
                    803:                    done = is_real = 1;
                    804:                    break;
                    805:                  default:
                    806:                    abort ();
                    807:                }
                    808:            }
                    809:          if (is_integral)
                    810:            {
                    811:              if (**mangled == 'm')
                    812:                {
                    813:                  string_appendn (tname, "-", 1);
                    814:                  (*mangled)++;
                    815:                }
                    816:              while (isdigit (**mangled))       
                    817:                {
                    818:                  string_appendn (tname, *mangled, 1);
                    819:                  (*mangled)++;
                    820:                }
                    821:            }
                    822:          else if (is_real)
                    823:            {
                    824:              if (**mangled == 'm')
                    825:                {
                    826:                  string_appendn (tname, "-", 1);
                    827:                  (*mangled)++;
                    828:                }
                    829:              while (isdigit (**mangled))       
                    830:                {
                    831:                  string_appendn (tname, *mangled, 1);
                    832:                  (*mangled)++;
                    833:                }
                    834:              if (**mangled == '.') /* fraction */
                    835:                {
                    836:                  string_appendn (tname, ".", 1);
                    837:                  (*mangled)++;
                    838:                  while (isdigit (**mangled))   
                    839:                    {
                    840:                      string_appendn (tname, *mangled, 1);
                    841:                      (*mangled)++;
                    842:                    }
                    843:                }
                    844:              if (**mangled == 'e') /* exponent */
                    845:                {
                    846:                  string_appendn (tname, "e", 1);
                    847:                  (*mangled)++;
                    848:                  while (isdigit (**mangled))   
                    849:                    {
                    850:                      string_appendn (tname, *mangled, 1);
                    851:                      (*mangled)++;
                    852:                    }
                    853:                }
                    854:            }
                    855:          else if (is_pointer)
                    856:            {
                    857:              if (!get_count (mangled, &symbol_len))
                    858:                {
                    859:                  success = 0;
                    860:                  break;
                    861:                }
                    862:              string_appendn (tname, *mangled, symbol_len);
                    863:              *mangled += symbol_len;
                    864:            }
                    865:        }
                    866:       need_comma = 1;
                    867:     }
                    868:   string_append (tname, ">");
                    869:   
                    870: /*
                    871:       if (work -> static_type)
                    872:        {
                    873:          string_append (declp, *mangled + 1);
                    874:          *mangled += strlen (*mangled);
                    875:          success = 1;
                    876:        }
                    877:       else
                    878:        {
                    879:          success = demangle_args (work, mangled, declp);
                    880:        }
                    881:     }
                    882: */
                    883:   return (success);
                    884: }
                    885: 
                    886: static int
                    887: arm_pt (work, mangled, n, anchor, args)
                    888:      struct work_stuff *work;
                    889:      CONST char *mangled;
                    890:      int n;
                    891:      CONST char **anchor, **args;
                    892: {
                    893:   /* ARM template? */
                    894:   if (ARM_DEMANGLING && (*anchor = strstr(mangled, "__pt__")))
                    895:     {
                    896:        int len;
                    897:         *args = *anchor + 6;
                    898:        len = consume_count (args);
                    899:         if (*args + len == mangled + n && **args == '_')
                    900:          {
                    901:            ++*args;
                    902:            return 1;
                    903:          }
                    904:     }
                    905:   return 0;
                    906: }
                    907: 
                    908: static int
                    909: demangle_class_name (work, mangled, declp)
                    910:      struct work_stuff *work;
                    911:      CONST char **mangled;
                    912:      string *declp;
                    913: {
                    914:   int n;
                    915:   int success = 0;
                    916: 
                    917:   n = consume_count (mangled);
                    918:   if (strlen (*mangled) >= n)
                    919:     {
                    920:       CONST char *p;
                    921:       CONST char *args;
                    922:       CONST char *e = *mangled + n;
                    923:       /* ARM template? */
                    924:       if (arm_pt (work, *mangled, n, &p, &args))
                    925:        {
                    926:          string arg;
                    927:          string_init (&arg);
                    928:          string_appendn (declp, *mangled, p - *mangled);
                    929:          string_append (declp, "<");
                    930:          /* should do error checking here */
                    931:          while (args < e) {
                    932:            string_clear (&arg);
                    933:            do_type (work, &args, &arg);
                    934:            string_appends (declp, &arg);
                    935:            string_append (declp, ",");
                    936:          }
                    937:          string_delete (&arg);
                    938:          --declp->p;
                    939:          string_append (declp, ">");
                    940:         }
                    941:       else
                    942:        {
                    943:          string_appendn (declp, *mangled, n);
                    944:         }
                    945:       *mangled += n;
                    946:       success = 1;
                    947:     }
                    948:   return (success);
                    949: }
                    950: 
                    951: /*
                    952: 
                    953: LOCAL FUNCTION
                    954: 
                    955:        demangle_class -- demangle a mangled class sequence
                    956: 
                    957: SYNOPSIS
                    958: 
                    959:        static int
                    960:        demangle_class (struct work_stuff *work, const char **mangled,
                    961:                        strint *declp)
                    962: 
                    963: DESCRIPTION
                    964: 
                    965:        DECLP points to the buffer into which demangling is being done.
                    966: 
                    967:        *MANGLED points to the current token to be demangled.  On input,
                    968:        it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
                    969:        On exit, it points to the next token after the mangled class on
                    970:        success, or the first unconsumed token on failure.
                    971: 
                    972:        If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
                    973:        we are demangling a constructor or destructor.  In this case
                    974:        we prepend "class::class" or "class::~class" to DECLP.
                    975: 
                    976:        Otherwise, we prepend "class::" to the current DECLP.
                    977: 
                    978:        Reset the constructor/destructor flags once they have been
                    979:        "consumed".  This allows demangle_class to be called later during
                    980:        the same demangling, to do normal class demangling.
                    981: 
                    982:        Returns 1 if demangling is successful, 0 otherwise.
                    983: 
                    984: */
                    985: 
                    986: static int
                    987: demangle_class (work, mangled, declp)
                    988:      struct work_stuff *work;
                    989:      CONST char **mangled;
                    990:      string *declp;
                    991: {
                    992:   int success = 0;
                    993:   string class_name;
                    994: 
                    995:   string_init (&class_name);
                    996:   if (demangle_class_name (work, mangled, &class_name))
                    997:     {
                    998:       if ((work->constructor & 1) || (work->destructor & 1))
                    999:        {
                   1000:          string_prepends (declp, &class_name);
                   1001:          if (work -> destructor & 1)
                   1002:            {
                   1003:              string_prepend (declp, "~");
                   1004:               work -> destructor -= 1;
                   1005:            }
                   1006:          else
                   1007:            {
                   1008:              work -> constructor -= 1; 
                   1009:            }
                   1010:        }
                   1011:       string_prepend (declp, "::");
                   1012:       string_prepends (declp, &class_name);
                   1013:       success = 1;
                   1014:     }
                   1015:   string_delete (&class_name);
                   1016:   return (success);
                   1017: }
                   1018: 
                   1019: /*
                   1020: 
                   1021: LOCAL FUNCTION
                   1022: 
                   1023:        demangle_prefix -- consume the mangled name prefix and find signature
                   1024: 
                   1025: SYNOPSIS
                   1026: 
                   1027:        static int
                   1028:        demangle_prefix (struct work_stuff *work, const char **mangled,
                   1029:                         string *declp);
                   1030: 
                   1031: DESCRIPTION
                   1032: 
                   1033:        Consume and demangle the prefix of the mangled name.
                   1034: 
                   1035:        DECLP points to the string buffer into which demangled output is
                   1036:        placed.  On entry, the buffer is empty.  On exit it contains
                   1037:        the root function name, the demangled operator name, or in some
                   1038:        special cases either nothing or the completely demangled result.
                   1039: 
                   1040:        MANGLED points to the current pointer into the mangled name.  As each
                   1041:        token of the mangled name is consumed, it is updated.  Upon entry
                   1042:        the current mangled name pointer points to the first character of
                   1043:        the mangled name.  Upon exit, it should point to the first character
                   1044:        of the signature if demangling was successful, or to the first
                   1045:        unconsumed character if demangling of the prefix was unsuccessful.
                   1046:        
                   1047:        Returns 1 on success, 0 otherwise.
                   1048:  */
                   1049: 
                   1050: static int
                   1051: demangle_prefix (work, mangled, declp)
                   1052:      struct work_stuff *work;
                   1053:      CONST char **mangled;
                   1054:      string *declp;
                   1055: {
                   1056:   int success = 1;
                   1057:   CONST char *scan;
                   1058:   int i;
                   1059: 
                   1060:   if (strncmp(*mangled, "_GLOBAL_$D$", 11) == 0)
                   1061:     {
                   1062:       /* it's a GNU global destructor to be executed at program exit */
                   1063:       (*mangled) += 11;
                   1064:       work->destructor = 2;
                   1065:     }
                   1066:   else if (strncmp(*mangled, "_GLOBAL_$I$", 11) == 0)
                   1067:     {
                   1068:       /* it's a GNU global constructor to be executed at program initial */
                   1069:       (*mangled) += 11;
                   1070:       work->constructor = 2;
                   1071:     }
                   1072:   else if (ARM_DEMANGLING && strncmp(*mangled, "__std__", 7) == 0)
                   1073:     {
                   1074:       /* it's a ARM global destructor to be executed at program exit */
                   1075:       (*mangled) += 7;
                   1076:       work->destructor = 2;
                   1077:     }
                   1078:   else if (ARM_DEMANGLING && strncmp(*mangled, "__sti__", 7) == 0)
                   1079:     {
                   1080:       /* it's a ARM global constructor to be executed at program initial */
                   1081:       (*mangled) += 7;
                   1082:       work->constructor = 2;
                   1083:     }
                   1084: 
                   1085: /*  This block of code is a reduction in strength time optimization
                   1086:     of:
                   1087:        scan = strstr (*mangled, "__"); */
                   1088: 
                   1089:   {
                   1090:     scan = *mangled;
                   1091: 
                   1092:     do {
                   1093:       scan = strchr (scan, '_');
                   1094:     } while (scan != NULL && *++scan != '_');
                   1095: 
                   1096:     if (scan != NULL) --scan;
                   1097:   }
                   1098: 
                   1099:   if (scan != NULL)
                   1100:     {
                   1101:       /* We found a sequence of two or more '_', ensure that we start at
                   1102:         the last pair in the sequence. */
                   1103:       i = strspn (scan, "_");
                   1104:       if (i > 2)
                   1105:        {
                   1106:          scan += (i - 2); 
                   1107:        }
                   1108:     }
                   1109:  
                   1110:   if (scan == NULL)
                   1111:     {
                   1112:       success = 0;
                   1113:     }
                   1114:   else if (work -> static_type)
                   1115:     {
                   1116:       if (!isdigit (scan[0]) && (scan[0] != 't'))
                   1117:        {
                   1118:          success = 0;
                   1119:        }
                   1120:     }
                   1121:   else if ((scan == *mangled) &&
                   1122:           (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't')))
                   1123:     {
                   1124:       /* The ARM says nothing about the mangling of local variables.
                   1125:         But cfront mangles local variables by prepending __<nesting_level>
                   1126:         to them. As an extension to ARM demangling we handle this case.  */
                   1127:       if ((LUCID_DEMANGLING || ARM_DEMANGLING) && isdigit (scan[2]))
                   1128:        {
                   1129:          *mangled = scan + 2;
                   1130:          consume_count (mangled);
                   1131:          string_append (declp, *mangled);
                   1132:          *mangled += strlen (*mangled);
                   1133:          success = 1; 
                   1134:        }
                   1135:       else
                   1136:        {
                   1137:       /* A GNU style constructor starts with "__[0-9Qt]. */
                   1138:           work -> constructor += 1;
                   1139:           *mangled = scan + 2;
                   1140:        }
                   1141:     }
                   1142:   else if ((scan == *mangled) && !isdigit (scan[2]) && (scan[2] != 't'))
                   1143:     {
                   1144:       /* Mangled name starts with "__".  Skip over any leading '_' characters,
                   1145:         then find the next "__" that separates the prefix from the signature.
                   1146:         */
                   1147:       if (!(ARM_DEMANGLING || LUCID_DEMANGLING)
                   1148:          || (arm_special (work, mangled, declp) == 0))
                   1149:        {
                   1150:          while (*scan == '_')
                   1151:            {
                   1152:              scan++;
                   1153:            }
                   1154:          if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
                   1155:            {
                   1156:              /* No separator (I.E. "__not_mangled"), or empty signature
                   1157:                 (I.E. "__not_mangled_either__") */
                   1158:              success = 0;
                   1159:            }
                   1160:          else
                   1161:            {
                   1162:              demangle_function_name (work, mangled, declp, scan);
                   1163:            }
                   1164:        }
                   1165:     }
                   1166:   else if (*(scan + 2) != '\0')
                   1167:     {
                   1168:       /* Mangled name does not start with "__" but does have one somewhere
                   1169:         in there with non empty stuff after it.  Looks like a global
                   1170:         function name. */
                   1171:       demangle_function_name (work, mangled, declp, scan);
                   1172:     }
                   1173:   else
                   1174:     {
                   1175:       /* Doesn't look like a mangled name */
                   1176:       success = 0;
                   1177:     }
                   1178: 
                   1179:   if (!success && (work->constructor == 2 || work->destructor == 2))
                   1180:     {
                   1181:       string_append (declp, *mangled);
                   1182:       *mangled += strlen (*mangled);
                   1183:       success = 1;
                   1184:     } 
                   1185:   return (success);
                   1186: }
                   1187: 
                   1188: /*
                   1189: 
                   1190: LOCAL FUNCTION
                   1191: 
                   1192:        gnu_special -- special handling of gnu mangled strings
                   1193: 
                   1194: SYNOPSIS
                   1195: 
                   1196:        static int
                   1197:        gnu_special (struct work_stuff *work, const char **mangled,
                   1198:                     string *declp);
                   1199: 
                   1200: 
                   1201: DESCRIPTION
                   1202: 
                   1203:        Process some special GNU style mangling forms that don't fit
                   1204:        the normal pattern.  For example:
                   1205: 
                   1206:                _$_3foo         (destructor for class foo)
                   1207:                _vt$foo         (foo virtual table)
                   1208:                _vt$foo$bar     (foo::bar virtual table)
                   1209:                _3foo$varname   (static data member)
                   1210:                _Q22rs2tu$vw    (static data member)
                   1211:                __t6vector1Zii  (constructor with template)
                   1212:  */
                   1213: 
                   1214: static int
                   1215: gnu_special (work, mangled, declp)
                   1216:      struct work_stuff *work;
                   1217:      CONST char **mangled;
                   1218:      string *declp;
                   1219: {
                   1220:   int n;
                   1221:   int success = 1;
                   1222:   CONST char *p;
                   1223: 
                   1224:   if ((*mangled)[0] == '_'
                   1225:       && strchr (cplus_markers, (*mangled)[1]) != NULL
                   1226:       && (*mangled)[2] == '_')
                   1227:     {
                   1228:       /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
                   1229:       (*mangled) += 3;
                   1230:       work -> destructor += 1;
                   1231:     }
                   1232:   else if ((*mangled)[0] == '_'
                   1233:           && (*mangled)[1] == 'v'
                   1234:           && (*mangled)[2] == 't'
                   1235:           && strchr (cplus_markers, (*mangled)[3]) != NULL)
                   1236:     {
                   1237:       /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
                   1238:          and create the decl.  Note that we consume the entire mangled
                   1239:         input string, which means that demangle_signature has no work
                   1240:         to do. */
                   1241:       (*mangled) += 4;
                   1242:       while (**mangled != '\0')
                   1243:        {
                   1244:          if (isdigit(*mangled[0]))
                   1245:            {
                   1246:              n = consume_count(mangled);
                   1247:            }
                   1248:          else
                   1249:            {
                   1250:              n = strcspn (*mangled, cplus_markers);
                   1251:            }
                   1252:          string_appendn (declp, *mangled, n);
                   1253:          (*mangled) += n;
                   1254:          
                   1255:          if (**mangled != '\0')
                   1256:            {
                   1257:              string_append (declp, "::");
                   1258:              (*mangled)++;
                   1259:            }
                   1260:        }
                   1261:       string_append (declp, " virtual table");
                   1262:     }
                   1263:   else if ((*mangled)[0] == '_'
                   1264:           && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
                   1265:           && (p = strpbrk (*mangled, cplus_markers)) != NULL)
                   1266:     {
                   1267:       /* static data member, "_3foo$varname" for example */
                   1268:       (*mangled)++;
                   1269:       switch (**mangled)
                   1270:        {
                   1271:          case 'Q':
                   1272:            success = demangle_qualified (work, mangled, declp, 0, 1);
                   1273:            break;
                   1274:          case 't':
                   1275:            success = demangle_template (work, mangled, declp, 0);
                   1276:            break;
                   1277:          default:
                   1278:            n = consume_count (mangled);
                   1279:            string_appendn (declp, *mangled, n);
                   1280:            (*mangled) += n;
                   1281:        }
                   1282:       if (success && (p == *mangled))
                   1283:        {
                   1284:          /* Consumed everything up to the cplus_marker, append the
                   1285:             variable name. */
                   1286:          (*mangled)++;
                   1287:          string_append (declp, "::");
                   1288:          n = strlen (*mangled);
                   1289:          string_appendn (declp, *mangled, n);
                   1290:          (*mangled) += n;
                   1291:        }
                   1292:       else
                   1293:        {
                   1294:          success = 0;
                   1295:        }
                   1296:     }
                   1297:   else
                   1298:     {
                   1299:       success = 0;
                   1300:     }
                   1301:   return (success);
                   1302: }
                   1303: 
                   1304: /*
                   1305: 
                   1306: LOCAL FUNCTION
                   1307: 
                   1308:        arm_special -- special handling of ARM/lucid mangled strings
                   1309: 
                   1310: SYNOPSIS
                   1311: 
                   1312:        static int
                   1313:        arm_special (struct work_stuff *work, const char **mangled,
                   1314:                        string *declp);
                   1315: 
                   1316: 
                   1317: DESCRIPTION
                   1318: 
                   1319:        Process some special ARM style mangling forms that don't fit
                   1320:        the normal pattern.  For example:
                   1321: 
                   1322:                __vtbl__3foo            (foo virtual table)
                   1323:                __vtbl__3foo__3bar      (bar::foo virtual table)
                   1324: 
                   1325:  */
                   1326: 
                   1327: static int
                   1328: arm_special (work, mangled, declp)
                   1329:      struct work_stuff *work;
                   1330:      CONST char **mangled;
                   1331:      string *declp;
                   1332: {
                   1333:   int n;
                   1334:   int success = 1;
                   1335:   CONST char *scan;
                   1336: 
                   1337:   if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
                   1338:     {
                   1339:       /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
                   1340:          and create the decl.  Note that we consume the entire mangled
                   1341:         input string, which means that demangle_signature has no work
                   1342:         to do. */
                   1343:       scan = *mangled + ARM_VTABLE_STRLEN;
                   1344:       while (*scan != '\0')        /* first check it can be demangled */
                   1345:         {
                   1346:           n = consume_count (&scan);
                   1347:           if (n==0)
                   1348:            {
                   1349:              return (0);           /* no good */
                   1350:            }
                   1351:           scan += n;
                   1352:           if (scan[0] == '_' && scan[1] == '_')
                   1353:            {
                   1354:              scan += 2;
                   1355:            }
                   1356:         }
                   1357:       (*mangled) += ARM_VTABLE_STRLEN;
                   1358:       while (**mangled != '\0')
                   1359:        {
                   1360:          n = consume_count (mangled);
                   1361:          string_prependn (declp, *mangled, n);
                   1362:          (*mangled) += n;
                   1363:          if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
                   1364:            {
                   1365:              string_prepend (declp, "::");
                   1366:              (*mangled) += 2;
                   1367:            }
                   1368:        }
                   1369:       string_append (declp, " virtual table");
                   1370:     }
                   1371:   else
                   1372:     {
                   1373:       success = 0;
                   1374:     }
                   1375:   return (success);
                   1376: }
                   1377: 
                   1378: /*
                   1379: 
                   1380: LOCAL FUNCTION
                   1381: 
                   1382:        demangle_qualified -- demangle 'Q' qualified name strings
                   1383: 
                   1384: SYNOPSIS
                   1385: 
                   1386:        static int
                   1387:        demangle_qualified (struct work_stuff *, const char *mangled,
                   1388:                            string *result, int isfuncname, int append);
                   1389: 
                   1390: DESCRIPTION
                   1391: 
                   1392:        Demangle a qualified name, such as "Q25Outer5Inner" which is
                   1393:        the mangled form of "Outer::Inner".  The demangled output is
                   1394:        prepended or appended to the result string according to the
                   1395:        state of the append flag.
                   1396: 
                   1397:        If isfuncname is nonzero, then the qualified name we are building
                   1398:        is going to be used as a member function name, so if it is a
                   1399:        constructor or destructor function, append an appropriate
                   1400:        constructor or destructor name.  I.E. for the above example,
                   1401:        the result for use as a constructor is "Outer::Inner::Inner"
                   1402:        and the result for use as a destructor is "Outer::Inner::~Inner".
                   1403: 
                   1404: BUGS
                   1405: 
                   1406:        Numeric conversion is ASCII dependent (FIXME).
                   1407: 
                   1408:  */
                   1409: 
                   1410: static int
                   1411: demangle_qualified (work, mangled, result, isfuncname, append)
                   1412:      struct work_stuff *work;
                   1413:      CONST char **mangled;
                   1414:      string *result;
                   1415:      int isfuncname;
                   1416:      int append;
                   1417: {
                   1418:   int qualifiers;
                   1419:   int namelength;
                   1420:   int success = 1;
                   1421:   CONST char *p;
                   1422:   char num[2];
                   1423:   string temp;
                   1424: 
                   1425:   string_init (&temp);
                   1426:   switch ((*mangled)[1])
                   1427:     {
                   1428:     case '_':
                   1429:       /* GNU mangled name with more than 9 classes.  The count is preceded
                   1430:         by an underscore (to distinguish it from the <= 9 case) and followed
                   1431:         by an underscore.  */
                   1432:       p = *mangled + 2;
                   1433:       qualifiers = atoi (p);
                   1434:       if (!isdigit (*p) || *p == '0')
                   1435:        success = 0;
                   1436: 
                   1437:       /* Skip the digits.  */
                   1438:       while (isdigit (*p))
                   1439:        ++p;
                   1440: 
                   1441:       if (*p != '_')
                   1442:        success = 0;
                   1443: 
                   1444:       *mangled = p + 1;
                   1445:       break;
                   1446: 
                   1447:     case '1':
                   1448:     case '2':
                   1449:     case '3':
                   1450:     case '4':
                   1451:     case '5':
                   1452:     case '6':
                   1453:     case '7':
                   1454:     case '8':
                   1455:     case '9':
                   1456:       /* The count is in a single digit.  */
                   1457:       num[0] = (*mangled)[1];
                   1458:       num[1] = '\0';
                   1459:       qualifiers = atoi (num);
                   1460: 
                   1461:       /* If there is an underscore after the digit, skip it.  This is
                   1462:         said to be for ARM-qualified names, but the ARM makes no
                   1463:         mention of such an underscore.  Perhaps cfront uses one.  */
                   1464:       if ((*mangled)[2] == '_')
                   1465:        {
                   1466:          (*mangled)++;
                   1467:        }
                   1468:       (*mangled) += 2;
                   1469:       break;
                   1470: 
                   1471:     case '0':
                   1472:     default:
                   1473:       success = 0;
                   1474:     }
                   1475: 
                   1476:   if (!success)
                   1477:     return success;
                   1478: 
                   1479:   /* Pick off the names and collect them in the temp buffer in the order
                   1480:      in which they are found, separated by '::'. */
                   1481: 
                   1482:   while (qualifiers-- > 0)
                   1483:     {
                   1484:       if (*mangled[0] == 't')
                   1485:        {
                   1486:          success = demangle_template(work, mangled, &temp, 0);
                   1487:          if (!success) break;
                   1488:        }
                   1489:       else
                   1490:         {      
                   1491:          namelength = consume_count (mangled);
                   1492:          if (strlen (*mangled) < namelength)
                   1493:            {
                   1494:            /* Simple sanity check failed */
                   1495:               success = 0;
                   1496:               break;
                   1497:            }
                   1498:          string_appendn (&temp, *mangled, namelength);
                   1499:          *mangled += namelength;
                   1500:        }
                   1501:       if (qualifiers > 0)
                   1502:         {
                   1503:           string_appendn (&temp, "::", 2);
                   1504:         }
                   1505:     }
                   1506: 
                   1507:   /* If we are using the result as a function name, we need to append
                   1508:      the appropriate '::' separated constructor or destructor name.
                   1509:      We do this here because this is the most convenient place, where
                   1510:      we already have a pointer to the name and the length of the name. */
                   1511: 
                   1512:   if (isfuncname && (work->constructor & 1 || work->destructor & 1))
                   1513:     {
                   1514:       string_appendn (&temp, "::", 2);
                   1515:       if (work -> destructor & 1)
                   1516:        {
                   1517:          string_append (&temp, "~");
                   1518:        }
                   1519:       string_appendn (&temp, (*mangled) - namelength, namelength);
                   1520:     }
                   1521: 
                   1522:   /* Now either prepend the temp buffer to the result, or append it, 
                   1523:      depending upon the state of the append flag. */
                   1524: 
                   1525:   if (append)
                   1526:     {
                   1527:       string_appends (result, &temp);
                   1528:     }
                   1529:   else
                   1530:     {
                   1531:       if (!STRING_EMPTY (result))
                   1532:        {
                   1533:          string_appendn (&temp, "::", 2);
                   1534:        }
                   1535:       string_prepends (result, &temp);
                   1536:     }
                   1537: 
                   1538:   string_delete (&temp);
                   1539:   return (success);
                   1540: }
                   1541: 
                   1542: /*
                   1543: 
                   1544: LOCAL FUNCTION
                   1545: 
                   1546:        get_count -- convert an ascii count to integer, consuming tokens
                   1547: 
                   1548: SYNOPSIS
                   1549: 
                   1550:        static int
                   1551:        get_count (const char **type, int *count)
                   1552: 
                   1553: DESCRIPTION
                   1554: 
                   1555:        Return 0 if no conversion is performed, 1 if a string is converted.
                   1556: */
                   1557: 
                   1558: static int
                   1559: get_count (type, count)
                   1560:      CONST char **type;
                   1561:      int *count;
                   1562: {
                   1563:   CONST char *p;
                   1564:   int n;
                   1565: 
                   1566:   if (!isdigit (**type))
                   1567:     {
                   1568:       return (0);
                   1569:     }
                   1570:   else
                   1571:     {
                   1572:       *count = **type - '0';
                   1573:       (*type)++;
                   1574:       if (isdigit (**type))
                   1575:        {
                   1576:          p = *type;
                   1577:          n = *count;
                   1578:          do 
                   1579:            {
                   1580:              n *= 10;
                   1581:              n += *p - '0';
                   1582:              p++;
                   1583:            } 
                   1584:          while (isdigit (*p));
                   1585:          if (*p == '_')
                   1586:            {
                   1587:              *type = p + 1;
                   1588:              *count = n;
                   1589:            }
                   1590:        }
                   1591:     }
                   1592:   return (1);
                   1593: }
                   1594: 
                   1595: /* result will be initialised here; it will be freed on failure */
                   1596: 
                   1597: static int
                   1598: do_type (work, mangled, result)
                   1599:      struct work_stuff *work;
                   1600:      CONST char **mangled;
                   1601:      string *result;
                   1602: {
                   1603:   int n;
                   1604:   int done;
                   1605:   int success;
                   1606:   string decl;
                   1607:   CONST char *remembered_type;
                   1608:   int constp;
                   1609:   int volatilep;
                   1610: 
                   1611:   string_init (&decl);
                   1612:   string_init (result);
                   1613: 
                   1614:   done = 0;
                   1615:   success = 1;
                   1616:   while (success && !done)
                   1617:     {
                   1618:       int member;
                   1619:       switch (**mangled)
                   1620:        {
                   1621: 
                   1622:        /* A pointer type */
                   1623:        case 'P':
                   1624:          (*mangled)++;
                   1625:          string_prepend (&decl, "*");
                   1626:          break;
                   1627: 
                   1628:        /* A reference type */
                   1629:        case 'R':
                   1630:          (*mangled)++;
                   1631:          string_prepend (&decl, "&");
                   1632:          break;
                   1633: 
                   1634:        /* An array */
                   1635:        case 'A':
                   1636:          {
                   1637:            CONST char *p = ++(*mangled);
                   1638: 
                   1639:            string_prepend (&decl, "(");
                   1640:            string_append (&decl, ")[");
                   1641:            /* Copy anything up until the next underscore (the size of the
                   1642:               array).  */
                   1643:            while (**mangled && **mangled != '_')
                   1644:              ++(*mangled);
                   1645:            if (**mangled == '_')
                   1646:              {
                   1647:                string_appendn (&decl, p, *mangled - p);
                   1648:                string_append (&decl, "]");             
                   1649:                *mangled += 1;
                   1650:              }
                   1651:            else
                   1652:              success = 0;
                   1653:            break;
                   1654:          }
                   1655: 
                   1656:        /* A back reference to a previously seen type */
                   1657:        case 'T':
                   1658:          (*mangled)++;
                   1659:          if (!get_count (mangled, &n) || n >= work -> ntypes)
                   1660:            {
                   1661:              success = 0;
                   1662:            }
                   1663:          else
                   1664:            {
                   1665:              remembered_type = work -> typevec[n];
                   1666:              mangled = &remembered_type;
                   1667:            }
                   1668:          break;
                   1669: 
                   1670:        /* A function */
                   1671:        case 'F':
                   1672:          (*mangled)++;
                   1673:          if (!STRING_EMPTY (&decl) && decl.b[0] == '*')
                   1674:            {
                   1675:              string_prepend (&decl, "(");
                   1676:              string_append (&decl, ")");
                   1677:            }
                   1678:          /* After picking off the function args, we expect to either find the
                   1679:             function return type (preceded by an '_') or the end of the
                   1680:             string. */
                   1681:          if (!demangle_args (work, mangled, &decl)
                   1682:              || (**mangled != '_' && **mangled != '\0'))
                   1683:            {
                   1684:              success = 0;
                   1685:            }
                   1686:          if (success && (**mangled == '_'))
                   1687:            {
                   1688:              (*mangled)++;
                   1689:            }
                   1690:          break;
                   1691: 
                   1692:        case 'M':
                   1693:        case 'O':
                   1694:          {
                   1695:            constp = 0;
                   1696:            volatilep = 0;
                   1697: 
                   1698:            member = **mangled == 'M';
                   1699:            (*mangled)++;
                   1700:            if (!isdigit (**mangled))
                   1701:              {
                   1702:                success = 0;
                   1703:                break;
                   1704:              }
                   1705:            n = consume_count (mangled);
                   1706:            if (strlen (*mangled) < n)
                   1707:              {
                   1708:                success = 0;
                   1709:                break;
                   1710:              }
                   1711:            string_append (&decl, ")");
                   1712:            string_prepend (&decl, "::");
                   1713:            string_prependn (&decl, *mangled, n);
                   1714:            string_prepend (&decl, "(");
                   1715:            *mangled += n;
                   1716:            if (member)
                   1717:              {
                   1718:                if (**mangled == 'C')
                   1719:                  {
                   1720:                    (*mangled)++;
                   1721:                    constp = 1;
                   1722:                  }
                   1723:                if (**mangled == 'V')
                   1724:                  {
                   1725:                    (*mangled)++;
                   1726:                    volatilep = 1;
                   1727:                  }
                   1728:                if (*(*mangled)++ != 'F')
                   1729:                  {
                   1730:                    success = 0;
                   1731:                    break;
                   1732:                  }
                   1733:              }
                   1734:            if ((member && !demangle_args (work, mangled, &decl))
                   1735:                || **mangled != '_')
                   1736:              {
                   1737:                success = 0;
                   1738:                break;
                   1739:              }
                   1740:            (*mangled)++;
                   1741:            if (! PRINT_ANSI_QUALIFIERS)
                   1742:              {
                   1743:                break;
                   1744:              }
                   1745:            if (constp)
                   1746:              {
                   1747:                APPEND_BLANK (&decl);
                   1748:                string_append (&decl, "const");
                   1749:              }
                   1750:            if (volatilep)
                   1751:              {
                   1752:                APPEND_BLANK (&decl);
                   1753:                string_append (&decl, "volatile");
                   1754:              }
                   1755:            break;
                   1756:          }
                   1757:         case 'G':
                   1758:            (*mangled)++;
                   1759:            break;
                   1760: 
                   1761:        case 'C':
                   1762:          (*mangled)++;
                   1763: /*
                   1764:          if ((*mangled)[1] == 'P')
                   1765:            {
                   1766: */
                   1767:              if (PRINT_ANSI_QUALIFIERS)
                   1768:                {
                   1769:                  if (!STRING_EMPTY (&decl))
                   1770:                    {
                   1771:                      string_prepend (&decl, " ");
                   1772:                    }
                   1773:                  string_prepend (&decl, "const");
                   1774:                }
                   1775:              break;
                   1776: /*
                   1777:            }
                   1778: */
                   1779: 
                   1780:          /* fall through */
                   1781:        default:
                   1782:          done = 1;
                   1783:          break;
                   1784:        }
                   1785:     }
                   1786: 
                   1787:   switch (**mangled)
                   1788:     {
                   1789:       /* A qualified name, such as "Outer::Inner". */
                   1790:       case 'Q':
                   1791:         success = demangle_qualified (work, mangled, result, 0, 1);
                   1792:        break;
                   1793: 
                   1794:       default:
                   1795:        success = demangle_fund_type (work, mangled, result);
                   1796:        break;
                   1797:     }
                   1798: 
                   1799:   if (success)
                   1800:     {
                   1801:       if (!STRING_EMPTY (&decl))
                   1802:        {
                   1803:          string_append (result, " ");
                   1804:          string_appends (result, &decl);
                   1805:        }
                   1806:     }
                   1807:   else
                   1808:     {
                   1809:       string_delete (result);
                   1810:     }
                   1811:   string_delete (&decl);
                   1812:   return (success);
                   1813: }
                   1814: 
                   1815: /* Given a pointer to a type string that represents a fundamental type
                   1816:    argument (int, long, unsigned int, etc) in TYPE, a pointer to the
                   1817:    string in which the demangled output is being built in RESULT, and
                   1818:    the WORK structure, decode the types and add them to the result.
                   1819: 
                   1820:    For example:
                   1821: 
                   1822:        "Ci"    =>      "const int"
                   1823:        "Sl"    =>      "signed long"
                   1824:        "CUs"   =>      "const unsigned short"
                   1825: 
                   1826:    */
                   1827: 
                   1828: static int
                   1829: demangle_fund_type (work, mangled, result)
                   1830:      struct work_stuff *work;
                   1831:      CONST char **mangled;
                   1832:      string *result;
                   1833: {
                   1834:   int done = 0;
                   1835:   int success = 1;
                   1836: 
                   1837:   /* First pick off any type qualifiers.  There can be more than one. */
                   1838: 
                   1839:   while (!done)
                   1840:     {
                   1841:       switch (**mangled)
                   1842:        {
                   1843:          case 'C':
                   1844:            (*mangled)++;
                   1845:            if (PRINT_ANSI_QUALIFIERS)
                   1846:              {
                   1847:                APPEND_BLANK (result);
                   1848:                string_append (result, "const");
                   1849:              }
                   1850:            break;
                   1851:          case 'U':
                   1852:            (*mangled)++;
                   1853:            APPEND_BLANK (result);
                   1854:            string_append (result, "unsigned");
                   1855:            break;
                   1856:          case 'S': /* signed char only */
                   1857:            (*mangled)++;
                   1858:            APPEND_BLANK (result);
                   1859:            string_append (result, "signed");
                   1860:            break;
                   1861:          case 'V':
                   1862:            (*mangled)++;
                   1863:            if (PRINT_ANSI_QUALIFIERS)
                   1864:              {
                   1865:                APPEND_BLANK (result);
                   1866:                string_append (result, "volatile");
                   1867:              }
                   1868:            break;
                   1869:          default:
                   1870:            done = 1;
                   1871:            break;
                   1872:        }
                   1873:     }
                   1874: 
                   1875:   /* Now pick off the fundamental type.  There can be only one. */
                   1876: 
                   1877:   switch (**mangled)
                   1878:     {
                   1879:       case '\0':
                   1880:       case '_':
                   1881:        break;
                   1882:       case 'v':
                   1883:        (*mangled)++;
                   1884:        APPEND_BLANK (result);
                   1885:        string_append (result, "void");
                   1886:        break;
                   1887:       case 'x':
                   1888:        (*mangled)++;
                   1889:        APPEND_BLANK (result);
                   1890:        string_append (result, "long long");
                   1891:        break;
                   1892:       case 'l':
                   1893:        (*mangled)++;
                   1894:        APPEND_BLANK (result);
                   1895:        string_append (result, "long");
                   1896:        break;
                   1897:       case 'i':
                   1898:        (*mangled)++;
                   1899:        APPEND_BLANK (result);
                   1900:        string_append (result, "int");
                   1901:        break;
                   1902:       case 's':
                   1903:        (*mangled)++;
                   1904:        APPEND_BLANK (result);
                   1905:        string_append (result, "short");
                   1906:        break;
                   1907:       case 'c':
                   1908:        (*mangled)++;
                   1909:        APPEND_BLANK (result);
                   1910:        string_append (result, "char");
                   1911:        break;
                   1912:       case 'w':
                   1913:        (*mangled)++;
                   1914:        APPEND_BLANK (result);
                   1915:        string_append (result, "wchar_t");
                   1916:        break;
                   1917:       case 'r':
                   1918:        (*mangled)++;
                   1919:        APPEND_BLANK (result);
                   1920:        string_append (result, "long double");
                   1921:        break;
                   1922:       case 'd':
                   1923:        (*mangled)++;
                   1924:        APPEND_BLANK (result);
                   1925:        string_append (result, "double");
                   1926:        break;
                   1927:       case 'f':
                   1928:        (*mangled)++;
                   1929:        APPEND_BLANK (result);
                   1930:        string_append (result, "float");
                   1931:        break;
                   1932:       case 'G':
                   1933:        (*mangled)++;
                   1934:        if (!isdigit (**mangled))
                   1935:          {
                   1936:            success = 0;
                   1937:            break;
                   1938:          }
                   1939:        /* fall through */
                   1940:       /* An explicit type, such as "6mytype" or "7integer" */
                   1941:       case '0':
                   1942:       case '1':
                   1943:       case '2':
                   1944:       case '3':
                   1945:       case '4':
                   1946:       case '5':
                   1947:       case '6':
                   1948:       case '7':
                   1949:       case '8':
                   1950:       case '9':
                   1951:        APPEND_BLANK (result);
                   1952:        if (!demangle_class_name (work, mangled, result)) {
                   1953:          --result->p;
                   1954:          success = 0;
                   1955:        }
                   1956:        break;
                   1957:       case 't':
                   1958:         success = demangle_template(work,mangled, result, 0);
                   1959:         break;
                   1960:       default:
                   1961:        success = 0;
                   1962:        break;
                   1963:       }
                   1964: 
                   1965:   return (success);
                   1966: }
                   1967: 
                   1968: /* `result' will be initialized in do_type; it will be freed on failure */
                   1969: 
                   1970: static int
                   1971: do_arg (work, mangled, result)
                   1972:      struct work_stuff *work;
                   1973:      CONST char **mangled;
                   1974:      string *result;
                   1975: {
                   1976:   CONST char *start = *mangled;
                   1977: 
                   1978:   if (!do_type (work, mangled, result))
                   1979:     {
                   1980:       return (0);
                   1981:     }
                   1982:   else
                   1983:     {
                   1984:       remember_type (work, start, *mangled - start);
                   1985:       return (1);
                   1986:     }
                   1987: }
                   1988: 
                   1989: static void
                   1990: remember_type (work, start, len)
                   1991:      struct work_stuff *work;
                   1992:      CONST char *start;
                   1993:      int len;
                   1994: {
                   1995:   char *tem;
                   1996: 
                   1997:   if (work -> ntypes >= work -> typevec_size)
                   1998:     {
                   1999:       if (work -> typevec_size == 0)
                   2000:        {
                   2001:          work -> typevec_size = 3;
                   2002:          work -> typevec =
                   2003:            (char **) xmalloc (sizeof (char *) * work -> typevec_size);
                   2004:        }
                   2005:       else
                   2006:        {
                   2007:          work -> typevec_size *= 2;
                   2008:          work -> typevec =
                   2009:            (char **) xrealloc ((char *)work -> typevec,
                   2010:                                sizeof (char *) * work -> typevec_size);
                   2011:        }
                   2012:     }
                   2013:   tem = xmalloc (len + 1);
                   2014:   memcpy (tem, start, len);
                   2015:   tem[len] = '\0';
                   2016:   work -> typevec[work -> ntypes++] = tem;
                   2017: }
                   2018: 
                   2019: /* Forget the remembered types, but not the type vector itself. */
                   2020: 
                   2021: static void
                   2022: forget_types (work)
                   2023:      struct work_stuff *work;
                   2024: {
                   2025:   int i;
                   2026: 
                   2027:   while (work -> ntypes > 0)
                   2028:     {
                   2029:       i = --(work -> ntypes);
                   2030:       if (work -> typevec[i] != NULL)
                   2031:        {
                   2032:          free (work -> typevec[i]);
                   2033:          work -> typevec[i] = NULL;
                   2034:        }
                   2035:     }
                   2036: }
                   2037: 
                   2038: /* Process the argument list part of the signature, after any class spec
                   2039:    has been consumed, as well as the first 'F' character (if any).  For
                   2040:    example:
                   2041: 
                   2042:    "__als__3fooRT0"            =>      process "RT0"
                   2043:    "complexfunc5__FPFPc_PFl_i" =>      process "PFPc_PFl_i"
                   2044: 
                   2045:    DECLP must be already initialised, usually non-empty.  It won't be freed
                   2046:    on failure.
                   2047: 
                   2048:    Note that g++ differs significantly from ARM and lucid style mangling
                   2049:    with regards to references to previously seen types.  For example, given
                   2050:    the source fragment:
                   2051: 
                   2052:      class foo {
                   2053:        public:
                   2054:        foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
                   2055:      };
                   2056: 
                   2057:      foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
                   2058:      void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
                   2059: 
                   2060:    g++ produces the names:
                   2061: 
                   2062:      __3fooiRT0iT2iT2
                   2063:      foo__FiR3fooiT1iT1
                   2064: 
                   2065:    while lcc (and presumably other ARM style compilers as well) produces:
                   2066: 
                   2067:      foo__FiR3fooT1T2T1T2
                   2068:      __ct__3fooFiR3fooT1T2T1T2
                   2069: 
                   2070:    Note that g++ bases it's type numbers starting at zero and counts all
                   2071:    previously seen types, while lucid/ARM bases it's type numbers starting
                   2072:    at one and only considers types after it has seen the 'F' character
                   2073:    indicating the start of the function args.  For lucid/ARM style, we
                   2074:    account for this difference by discarding any previously seen types when
                   2075:    we see the 'F' character, and subtracting one from the type number
                   2076:    reference.
                   2077: 
                   2078:  */
                   2079: 
                   2080: static int
                   2081: demangle_args (work, mangled, declp)
                   2082:      struct work_stuff *work;
                   2083:      CONST char **mangled;
                   2084:      string *declp;
                   2085: {
                   2086:   string arg;
                   2087:   int need_comma = 0;
                   2088:   int r;
                   2089:   int t;
                   2090:   CONST char *tem;
                   2091:   char temptype;
                   2092: 
                   2093:   if (PRINT_ARG_TYPES)
                   2094:     {
                   2095:       string_append (declp, "(");
                   2096:       if (**mangled == '\0')
                   2097:        {
                   2098:          string_append (declp, "void");
                   2099:        }
                   2100:     }
                   2101: 
                   2102:   while (**mangled != '_' && **mangled != '\0' && **mangled != 'e')
                   2103:     {
                   2104:       if ((**mangled == 'N') || (**mangled == 'T'))
                   2105:        {
                   2106:          temptype = *(*mangled)++;
                   2107:          
                   2108:          if (temptype == 'N')
                   2109:            {
                   2110:              if (!get_count (mangled, &r))
                   2111:                {
                   2112:                  return (0);
                   2113:                }
                   2114:            }
                   2115:          else
                   2116:            {
                   2117:              r = 1;
                   2118:            }
                   2119:          if (!get_count (mangled, &t))
                   2120:            {
                   2121:              return (0);
                   2122:            }
                   2123:          if (LUCID_DEMANGLING || ARM_DEMANGLING)
                   2124:            {
                   2125:              t--;
                   2126:            }
                   2127:          /* Validate the type index.  Protect against illegal indices from
                   2128:             malformed type strings. */
                   2129:          if ((t < 0) || (t >= work -> ntypes))
                   2130:            {
                   2131:              return (0);
                   2132:            }
                   2133:          while (--r >= 0)
                   2134:            {
                   2135:              tem = work -> typevec[t];
                   2136:              if (need_comma && PRINT_ARG_TYPES)
                   2137:                {
                   2138:                  string_append (declp, ", ");
                   2139:                }
                   2140:              if (!do_arg (work, &tem, &arg))
                   2141:                {
                   2142:                  return (0);
                   2143:                }
                   2144:              if (PRINT_ARG_TYPES)
                   2145:                {
                   2146:                  string_appends (declp, &arg);
                   2147:                }
                   2148:              string_delete (&arg);
                   2149:              need_comma = 1;
                   2150:            }
                   2151:        }
                   2152:       else
                   2153:        {
                   2154:          if (need_comma & PRINT_ARG_TYPES)
                   2155:            {
                   2156:              string_append (declp, ", ");
                   2157:            }
                   2158:          if (!do_arg (work, mangled, &arg))
                   2159:            {
                   2160:              return (0);
                   2161:            }
                   2162:          if (PRINT_ARG_TYPES)
                   2163:            {
                   2164:              string_appends (declp, &arg);
                   2165:            }
                   2166:          string_delete (&arg);
                   2167:          need_comma = 1;
                   2168:        }
                   2169:     }
                   2170: 
                   2171:   if (**mangled == 'e')
                   2172:     {
                   2173:       (*mangled)++;
                   2174:       if (PRINT_ARG_TYPES)
                   2175:        {
                   2176:          if (need_comma)
                   2177:            {
                   2178:              string_append (declp, ",");
                   2179:            }
                   2180:          string_append (declp, "...");
                   2181:        }
                   2182:     }
                   2183: 
                   2184:   if (PRINT_ARG_TYPES)
                   2185:     {
                   2186:       string_append (declp, ")");
                   2187:     }
                   2188:   return (1);
                   2189: }
                   2190: 
                   2191: static void
                   2192: demangle_function_name (work, mangled, declp, scan)
                   2193:      struct work_stuff *work;
                   2194:      CONST char **mangled;
                   2195:      string *declp;
                   2196:      CONST char *scan;
                   2197: {
                   2198:   int i;
                   2199:   int len;
                   2200:   string type;
                   2201:   CONST char *tem;
                   2202: 
                   2203:   string_appendn (declp, (*mangled), scan - (*mangled));
                   2204:   string_need (declp, 1);
                   2205:   *(declp -> p) = '\0';
                   2206: 
                   2207:   /* Consume the function name, including the "__" separating the name
                   2208:      from the signature.  We are guaranteed that SCAN points to the
                   2209:      separator. */
                   2210: 
                   2211:   (*mangled) = scan + 2;
                   2212: 
                   2213:   if (LUCID_DEMANGLING || ARM_DEMANGLING)
                   2214:     {
                   2215: 
                   2216:       /* See if we have an ARM style constructor or destructor operator.
                   2217:         If so, then just record it, clear the decl, and return.
                   2218:         We can't build the actual constructor/destructor decl until later,
                   2219:         when we recover the class name from the signature. */
                   2220: 
                   2221:       if (strcmp (declp -> b, "__ct") == 0)
                   2222:        {
                   2223:          work -> constructor += 1;
                   2224:          string_clear (declp);
                   2225:          return;
                   2226:        }
                   2227:       else if (strcmp (declp -> b, "__dt") == 0)
                   2228:        {
                   2229:          work -> destructor += 1;
                   2230:          string_clear (declp);
                   2231:          return;
                   2232:        }
                   2233:     }
                   2234: 
                   2235:   if (declp->p - declp->b >= 3 
                   2236:       && declp->b[0] == 'o'
                   2237:       && declp->b[1] == 'p'
                   2238:       && strchr (cplus_markers, declp->b[2]) != NULL)
                   2239:     {
                   2240:       /* see if it's an assignment expression */
                   2241:       if (declp->p - declp->b >= 10 /* op$assign_ */
                   2242:          && memcmp (declp->b + 3, "assign_", 7) == 0)
                   2243:        {
                   2244:          for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
                   2245:            {
                   2246:              len = declp->p - declp->b - 10;
                   2247:              if (strlen (optable[i].in) == len
                   2248:                  && memcmp (optable[i].in, declp->b + 10, len) == 0)
                   2249:                {
                   2250:                  string_clear (declp);
                   2251:                  string_append (declp, "operator");
                   2252:                  string_append (declp, optable[i].out);
                   2253:                  string_append (declp, "=");
                   2254:                  break;
                   2255:                }
                   2256:            }
                   2257:        }
                   2258:       else
                   2259:        {
                   2260:          for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
                   2261:            {
                   2262:              int len = declp->p - declp->b - 3;
                   2263:              if (strlen (optable[i].in) == len 
                   2264:                  && memcmp (optable[i].in, declp->b + 3, len) == 0)
                   2265:                {
                   2266:                  string_clear (declp);
                   2267:                  string_append (declp, "operator");
                   2268:                  string_append (declp, optable[i].out);
                   2269:                  break;
                   2270:                }
                   2271:            }
                   2272:        }
                   2273:     }
                   2274:   else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type$", 5) == 0)
                   2275:     {
                   2276:       /* type conversion operator */
                   2277:       tem = declp->b + 5;
                   2278:       if (do_type (work, &tem, &type))
                   2279:        {
                   2280:          string_clear (declp);
                   2281:          string_append (declp, "operator ");
                   2282:          string_appends (declp, &type);
                   2283:          string_delete (&type);
                   2284:        }
                   2285:     }
                   2286:   else if (declp->b[0] == '_' && declp->b[1] == '_'
                   2287:          && declp->b[2] == 'o' && declp->b[3] == 'p')
                   2288:     {
                   2289:       /* ANSI.  */
                   2290:       /* type conversion operator.  */
                   2291:       tem = declp->b + 4;
                   2292:       if (do_type (work, &tem, &type))
                   2293:        {
                   2294:          string_clear (declp);
                   2295:          string_append (declp, "operator ");
                   2296:          string_appends (declp, &type);
                   2297:          string_delete (&type);
                   2298:        }
                   2299:     }
                   2300:   else if (declp->b[0] == '_' && declp->b[1] == '_'
                   2301:           && declp->b[2] >= 'a' && declp->b[2] <= 'z'
                   2302:           && declp->b[3] >= 'a' && declp->b[3] <= 'z')
                   2303:     {
                   2304:       if (declp->b[4] == '\0')
                   2305:        {
                   2306:          /* Operator.  */
                   2307:          for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
                   2308:            {
                   2309:              if (strlen (optable[i].in) == 2
                   2310:                  && memcmp (optable[i].in, declp->b + 2, 2) == 0)
                   2311:                {
                   2312:                  string_clear (declp);
                   2313:                  string_append (declp, "operator");
                   2314:                  string_append (declp, optable[i].out);
                   2315:                  break;
                   2316:                }
                   2317:            }
                   2318:        }
                   2319:       else
                   2320:        {
                   2321:          if (declp->b[2] == 'a' && declp->b[5] == '\0')
                   2322:            {
                   2323:              /* Assignment. */
                   2324:              for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
                   2325:                {
                   2326:                  if (strlen (optable[i].in) == 3
                   2327:                      && memcmp (optable[i].in, declp->b + 2, 3) == 0)
                   2328:                    {
                   2329:                      string_clear (declp);
                   2330:                      string_append (declp, "operator");
                   2331:                      string_append (declp, optable[i].out);
                   2332:                      break;
                   2333:                    }                 
                   2334:                }
                   2335:            }
                   2336:        }
                   2337:     }
                   2338: }
                   2339: 
                   2340: /* a mini string-handling package */
                   2341: 
                   2342: static void
                   2343: string_need (s, n)
                   2344:      string *s;
                   2345:      int n;
                   2346: {
                   2347:   int tem;
                   2348: 
                   2349:   if (s->b == NULL)
                   2350:     {
                   2351:       if (n < 32)
                   2352:        {
                   2353:          n = 32;
                   2354:        }
                   2355:       s->p = s->b = xmalloc (n);
                   2356:       s->e = s->b + n;
                   2357:     }
                   2358:   else if (s->e - s->p < n)
                   2359:     {
                   2360:       tem = s->p - s->b;
                   2361:       n += tem;
                   2362:       n *= 2;
                   2363:       s->b = xrealloc (s->b, n);
                   2364:       s->p = s->b + tem;
                   2365:       s->e = s->b + n;
                   2366:     }
                   2367: }
                   2368: 
                   2369: static void
                   2370: string_delete (s)
                   2371:      string *s;
                   2372: {
                   2373:   if (s->b != NULL)
                   2374:     {
                   2375:       free (s->b);
                   2376:       s->b = s->e = s->p = NULL;
                   2377:     }
                   2378: }
                   2379: 
                   2380: static void
                   2381: string_init (s)
                   2382:      string *s;
                   2383: {
                   2384:   s->b = s->p = s->e = NULL;
                   2385: }
                   2386: 
                   2387: static void 
                   2388: string_clear (s)
                   2389:      string *s;
                   2390: {
                   2391:   s->p = s->b;
                   2392: }
                   2393: 
                   2394: #if 0
                   2395: 
                   2396: static int
                   2397: string_empty (s)
                   2398:      string *s;
                   2399: {
                   2400:   return (s->b == s->p);
                   2401: }
                   2402: 
                   2403: #endif
                   2404: 
                   2405: static void
                   2406: string_append (p, s)
                   2407:      string *p;
                   2408:      CONST char *s;
                   2409: {
                   2410:   int n;
                   2411:   if (s == NULL || *s == '\0')
                   2412:     return;
                   2413:   n = strlen (s);
                   2414:   string_need (p, n);
                   2415:   memcpy (p->p, s, n);
                   2416:   p->p += n;
                   2417: }
                   2418: 
                   2419: static void
                   2420: string_appends (p, s)
                   2421:      string *p, *s;
                   2422: {
                   2423:   int n;
                   2424: 
                   2425:   if (s->b != s->p)
                   2426:     {
                   2427:       n = s->p - s->b;
                   2428:       string_need (p, n);
                   2429:       memcpy (p->p, s->b, n);
                   2430:       p->p += n;
                   2431:     }
                   2432: }
                   2433: 
                   2434: static void
                   2435: string_appendn (p, s, n)
                   2436:      string *p;
                   2437:      CONST char *s;
                   2438:      int n;
                   2439: {
                   2440:   if (n != 0)
                   2441:     {
                   2442:       string_need (p, n);
                   2443:       memcpy (p->p, s, n);
                   2444:       p->p += n;
                   2445:     }
                   2446: }
                   2447: 
                   2448: static void
                   2449: string_prepend (p, s)
                   2450:      string *p;
                   2451:      CONST char *s;
                   2452: {
                   2453:   if (s != NULL && *s != '\0')
                   2454:     {
                   2455:       string_prependn (p, s, strlen (s));
                   2456:     }
                   2457: }
                   2458: 
                   2459: static void
                   2460: string_prepends (p, s)
                   2461:      string *p, *s;
                   2462: {
                   2463:   if (s->b != s->p)
                   2464:     {
                   2465:       string_prependn (p, s->b, s->p - s->b);
                   2466:     }
                   2467: }
                   2468: 
                   2469: static void
                   2470: string_prependn (p, s, n)
                   2471:      string *p;
                   2472:      CONST char *s;
                   2473:      int n;
                   2474: {
                   2475:   char *q;
                   2476: 
                   2477:   if (n != 0)
                   2478:     {
                   2479:       string_need (p, n);
                   2480:       for (q = p->p - 1; q >= p->b; q--)
                   2481:        {
                   2482:          q[n] = q[0];
                   2483:        }
                   2484:       memcpy (p->b, s, n);
                   2485:       p->p += n;
                   2486:     }
                   2487: }
                   2488: 
                   2489: /* To generate a standalone demangler program for testing purposes, just
                   2490:    compile and link this file with -DMAIN.   When run, it demangles each
                   2491:    command line arg, or each stdin string, and prints the result on stdout. */
                   2492: 
                   2493: #ifdef MAIN
                   2494: 
                   2495: static void
                   2496: demangle_it (mangled_name)
                   2497:   char *mangled_name;
                   2498: {
                   2499:   char *result;
                   2500: 
                   2501:   result = cplus_demangle (mangled_name, DMGL_PARAMS | DMGL_ANSI);
                   2502:   if (result == NULL)
                   2503:     {
                   2504:       printf ("%s\n", mangled_name);
                   2505:     }
                   2506:   else
                   2507:     {
                   2508:       printf ("%s\n", result);
                   2509:       free (result);
                   2510:     }
                   2511: }
                   2512: 
                   2513: char *
                   2514: xmalloc (size)
                   2515:     long size;
                   2516: {
                   2517:   char * newmem;
                   2518: 
                   2519:   if ((newmem = (char *) malloc ((int) size)) == NULL)
                   2520:     {
                   2521:       fprintf (stderr, "\nCan't allocate %u bytes\n", size);
                   2522:       exit (1);
                   2523:     }
                   2524:   return (newmem);
                   2525: }
                   2526: 
                   2527: char *
                   2528: xrealloc (oldmem, size)
                   2529:     PTR oldmem;
                   2530:     long size;
                   2531: {
                   2532:   char * newmem;
                   2533: 
                   2534:   if ((newmem = (char *) realloc ((char *) oldmem, (int) size)) == NULL)
                   2535:     {
                   2536:       fprintf (stderr, "\nCan't reallocate %u bytes\n", size);
                   2537:       exit (1);
                   2538:     }
                   2539:   return (newmem);
                   2540: }
                   2541: 
                   2542: #include "getopt.h"
                   2543: 
                   2544: static char *program_name;
                   2545: extern char *program_version;
                   2546: 
                   2547: static void
                   2548: usage (stream, status)
                   2549:      FILE *stream;
                   2550:      int status;
                   2551: {    
                   2552:   fprintf (stream, "\
                   2553: Usage: %s [-_] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
                   2554:        [--format={gnu,lucid,arm}] [--help] [--version] [arg...]\n",
                   2555:           program_name);
                   2556:   exit (status);
                   2557: }
                   2558: 
                   2559: #define MBUF_SIZE 512
                   2560: char mbuffer[MBUF_SIZE];
                   2561: 
                   2562: /* Defined in the automatically-generated ../binutils/underscore.c. */
                   2563: extern int prepends_underscore;
                   2564: 
                   2565: int strip_underscore = 0;
                   2566: 
                   2567: static struct option long_options[] = {
                   2568:   {"strip-underscores", no_argument, 0, '_'},
                   2569:   {"format", required_argument, 0, 's'},
                   2570:   {"help", no_argument, 0, 'h'},
                   2571:   {"version", no_argument, 0, 'v'},
                   2572:   {0, no_argument, 0, 0}
                   2573: };
                   2574: 
                   2575: int
                   2576: main (argc, argv)
                   2577:      int argc;
                   2578:      char **argv;
                   2579: {
                   2580:   char *result;
                   2581:   int c;
                   2582: 
                   2583:   program_name = argv[0];
                   2584:   strip_underscore = prepends_underscore;
                   2585: 
                   2586:   while ((c = getopt_long (argc, argv, "_s:", long_options, (int *) 0)) != EOF)
                   2587:     {
                   2588:       switch (c)
                   2589:        {
                   2590:          case '?':
                   2591:            usage (stderr, 1);
                   2592:            break;
                   2593:          case 'h':
                   2594:            usage (stdout, 0);
                   2595:          case 'v':
                   2596:            printf ("GNU %s version %s\n", program_name, program_version);
                   2597:            exit (0);
                   2598:          case '_':
                   2599:            strip_underscore = 1;
                   2600:            break;
                   2601:          case 's':
                   2602:            if (strcmp (optarg, "gnu") == 0)
                   2603:              {
                   2604:                current_demangling_style = gnu_demangling;
                   2605:              }
                   2606:            else if (strcmp (optarg, "lucid") == 0)
                   2607:              {
                   2608:                current_demangling_style = lucid_demangling;
                   2609:              }
                   2610:            else if (strcmp (optarg, "arm") == 0)
                   2611:              {
                   2612:                current_demangling_style = arm_demangling;
                   2613:              }
                   2614:            else
                   2615:              {
                   2616:                fprintf (stderr, "%s: unknown demangling style `%s'\n",
                   2617:                         program_name, optarg);
                   2618:                exit (1);
                   2619:              }
                   2620:            break;
                   2621:        }
                   2622:     }
                   2623: 
                   2624:   if (optind < argc)
                   2625:     {
                   2626:       for ( ; optind < argc; optind++)
                   2627:        {
                   2628:          demangle_it (argv[optind]);
                   2629:        }
                   2630:     }
                   2631:   else
                   2632:     {
                   2633:       for (;;)
                   2634:        {
                   2635:          int i = 0;
                   2636:          c = getchar ();
                   2637:          /* Try to read a label. */
                   2638:          while (c != EOF && (isalnum(c) || c == '_' || c == '$' || c == '.'))
                   2639:            {
                   2640:              if (i >= MBUF_SIZE-1)
                   2641:                break;
                   2642:              mbuffer[i++] = c;
                   2643:              c = getchar ();
                   2644:            }
                   2645:          if (i > 0)
                   2646:            {
                   2647:              int skip_first = strip_underscore && i > 1 && mbuffer[0] == '_';
                   2648:              mbuffer[i] = 0;
                   2649:              
                   2650:              result = cplus_demangle (mbuffer+skip_first,
                   2651:                                       DMGL_PARAMS | DMGL_ANSI);
                   2652:              if (result)
                   2653:                {
                   2654:                  fputs (result, stdout);
                   2655:                  free (result);
                   2656:                }
                   2657:              else
                   2658:                fputs (mbuffer + skip_first, stdout);
                   2659:            }
                   2660:          if (c == EOF)
                   2661:            break;
                   2662:          putchar (c);
                   2663:        }
                   2664:     }
                   2665: 
                   2666:   exit (0);
                   2667: }
                   2668: 
                   2669: #endif /* main */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.