Annotation of gcc/cplus-dem.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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