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

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

unix.superglobalmegacorp.com

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