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

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

unix.superglobalmegacorp.com

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