Annotation of GNUtools/debug/gdb/libiberty/cplus-dem.c, revision 1.1

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

unix.superglobalmegacorp.com

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