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

1.1       root        1: /* Demangler for GNU C++ 
                      2:    Copyright 1989, 1991 Free Software Foundation, Inc.
                      3:    Written by James Clark ([email protected])
                      4:    Rewritten by Fred Fish ([email protected]) for ARM and Lucid demangling
                      5:    
                      6: This file is part of the libiberty library.
                      7: Libiberty is free software; you can redistribute it and/or
                      8: modify it under the terms of the GNU Library General Public
                      9: License as published by the Free Software Foundation; either
                     10: version 2 of the License, or (at your option) any later version.
                     11: 
                     12: Libiberty is distributed in the hope that it will be useful,
                     13: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     15: Library General Public License for more details.
                     16: 
                     17: You should have received a copy of the GNU Library General Public
                     18: License along with libiberty; see the file COPYING.LIB.  If
                     19: not, write to the Free Software Foundation, Inc., 675 Mass Ave,
                     20: Cambridge, MA 02139, USA.  */
                     21: 
                     22: /* This 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.