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

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

unix.superglobalmegacorp.com

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