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

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

unix.superglobalmegacorp.com

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