xref: /dragonfly/contrib/gdb-7/libiberty/cplus-dem.c (revision ec70266467411565ead9166ad4c1dbb79ff7cd77)
1 /* Demangler for GNU C++
2    Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999,
3    2000, 2001, 2002, 2003, 2004, 2010 Free Software Foundation, Inc.
4    Written by James Clark (jjc@jclark.uucp)
5    Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
6    Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
7 
8 This file is part of the libiberty library.
9 Libiberty is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public
11 License as published by the Free Software Foundation; either
12 version 2 of the License, or (at your option) any later version.
13 
14 In addition to the permissions in the GNU Library General Public
15 License, the Free Software Foundation gives you unlimited permission
16 to link the compiled version of this file into combinations with other
17 programs, and to distribute those combinations without any restriction
18 coming from the use of this file.  (The Library Public License
19 restrictions do apply in other respects; for example, they cover
20 modification of the file, and distribution when not linked into a
21 combined executable.)
22 
23 Libiberty is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26 Library General Public License for more details.
27 
28 You should have received a copy of the GNU Library General Public
29 License along with libiberty; see the file COPYING.LIB.  If
30 not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
31 Boston, MA 02110-1301, USA.  */
32 
33 /* This file exports two functions; cplus_mangle_opname and cplus_demangle.
34 
35    This file imports xmalloc and xrealloc, which are like malloc and
36    realloc except that they generate a fatal error if there is no
37    available memory.  */
38 
39 /* This file lives in both GCC and libiberty.  When making changes, please
40    try not to break either.  */
41 
42 #ifdef HAVE_CONFIG_H
43 #include "config.h"
44 #endif
45 
46 #include "safe-ctype.h"
47 
48 #include <sys/types.h>
49 #include <string.h>
50 #include <stdio.h>
51 
52 #ifdef HAVE_STDLIB_H
53 #include <stdlib.h>
54 #else
55 void * malloc ();
56 void * realloc ();
57 #endif
58 
59 #include <demangle.h>
60 #undef CURRENT_DEMANGLING_STYLE
61 #define CURRENT_DEMANGLING_STYLE work->options
62 
63 #include "libiberty.h"
64 
65 #define min(X,Y) (((X) < (Y)) ? (X) : (Y))
66 
67 /* A value at least one greater than the maximum number of characters
68    that will be output when using the `%d' format with `printf'.  */
69 #define INTBUF_SIZE 32
70 
71 extern void fancy_abort (void) ATTRIBUTE_NORETURN;
72 
73 /* In order to allow a single demangler executable to demangle strings
74    using various common values of CPLUS_MARKER, as well as any specific
75    one set at compile time, we maintain a string containing all the
76    commonly used ones, and check to see if the marker we are looking for
77    is in that string.  CPLUS_MARKER is usually '$' on systems where the
78    assembler can deal with that.  Where the assembler can't, it's usually
79    '.' (but on many systems '.' is used for other things).  We put the
80    current defined CPLUS_MARKER first (which defaults to '$'), followed
81    by the next most common value, followed by an explicit '$' in case
82    the value of CPLUS_MARKER is not '$'.
83 
84    We could avoid this if we could just get g++ to tell us what the actual
85    cplus marker character is as part of the debug information, perhaps by
86    ensuring that it is the character that terminates the gcc<n>_compiled
87    marker symbol (FIXME).  */
88 
89 #if !defined (CPLUS_MARKER)
90 #define CPLUS_MARKER '$'
91 #endif
92 
93 enum demangling_styles current_demangling_style = auto_demangling;
94 
95 static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
96 
97 static char char_str[2] = { '\000', '\000' };
98 
99 void
set_cplus_marker_for_demangling(int ch)100 set_cplus_marker_for_demangling (int ch)
101 {
102   cplus_markers[0] = ch;
103 }
104 
105 typedef struct string                   /* Beware: these aren't required to be */
106 {                                       /*  '\0' terminated.  */
107   char *b;                              /* pointer to start of string */
108   char *p;                              /* pointer after last character */
109   char *e;                              /* pointer after end of allocated space */
110 } string;
111 
112 /* Stuff that is shared between sub-routines.
113    Using a shared structure allows cplus_demangle to be reentrant.  */
114 
115 struct work_stuff
116 {
117   int options;
118   char **typevec;
119   char **ktypevec;
120   char **btypevec;
121   int numk;
122   int numb;
123   int ksize;
124   int bsize;
125   int ntypes;
126   int typevec_size;
127   int constructor;
128   int destructor;
129   int static_type;  /* A static member function */
130   int temp_start;       /* index in demangled to start of template args */
131   int type_quals;       /* The type qualifiers.  */
132   int dllimported;  /* Symbol imported from a PE DLL */
133   char **tmpl_argvec;   /* Template function arguments. */
134   int ntmpl_args;       /* The number of template function arguments. */
135   int forgetting_types; /* Nonzero if we are not remembering the types
136                                  we see.  */
137   string* previous_argument; /* The last function argument demangled.  */
138   int nrepeats;         /* The number of times to repeat the previous
139                                  argument.  */
140 };
141 
142 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
143 #define PRINT_ARG_TYPES       (work -> options & DMGL_PARAMS)
144 
145 static const struct optable
146 {
147   const char *const in;
148   const char *const out;
149   const int flags;
150 } optable[] = {
151   {"nw",    " new", DMGL_ANSI},         /* new (1.92,        ansi) */
152   {"dl",    " delete",        DMGL_ANSI},         /* new (1.92,        ansi) */
153   {"new",   " new", 0},                 /* old (1.91,        and 1.x) */
154   {"delete",          " delete",        0},                 /* old (1.91,        and 1.x) */
155   {"vn",    " new []",        DMGL_ANSI},         /* GNU, pending ansi */
156   {"vd",    " delete []",     DMGL_ANSI},         /* GNU, pending ansi */
157   {"as",    "=",              DMGL_ANSI},         /* ansi */
158   {"ne",    "!=",             DMGL_ANSI},         /* old, ansi */
159   {"eq",    "==",             DMGL_ANSI},         /* old,   ansi */
160   {"ge",    ">=",             DMGL_ANSI},         /* old,   ansi */
161   {"gt",    ">",              DMGL_ANSI},         /* old,   ansi */
162   {"le",    "<=",             DMGL_ANSI},         /* old,   ansi */
163   {"lt",    "<",              DMGL_ANSI},         /* old,   ansi */
164   {"plus",            "+",              0},                 /* old */
165   {"pl",    "+",              DMGL_ANSI},         /* ansi */
166   {"apl",   "+=",             DMGL_ANSI},         /* ansi */
167   {"minus",           "-",              0},                 /* old */
168   {"mi",    "-",              DMGL_ANSI},         /* ansi */
169   {"ami",   "-=",             DMGL_ANSI},         /* ansi */
170   {"mult",            "*",              0},                 /* old */
171   {"ml",    "*",              DMGL_ANSI},         /* ansi */
172   {"amu",   "*=",             DMGL_ANSI},         /* ansi (ARM/Lucid) */
173   {"aml",   "*=",             DMGL_ANSI},         /* ansi (GNU/g++) */
174   {"convert",         "+",              0},                 /* old (unary +) */
175   {"negate",          "-",              0},                 /* old (unary -) */
176   {"trunc_mod",       "%",              0},                 /* old */
177   {"md",    "%",              DMGL_ANSI},         /* ansi */
178   {"amd",   "%=",             DMGL_ANSI},         /* ansi */
179   {"trunc_div",       "/",              0},                 /* old */
180   {"dv",    "/",              DMGL_ANSI},         /* ansi */
181   {"adv",   "/=",             DMGL_ANSI},         /* ansi */
182   {"truth_andif", "&&",                 0},                 /* old */
183   {"aa",    "&&",             DMGL_ANSI},         /* ansi */
184   {"truth_orif",  "||",                 0},                 /* old */
185   {"oo",    "||",             DMGL_ANSI},         /* ansi */
186   {"truth_not",       "!",              0},                 /* old */
187   {"nt",    "!",              DMGL_ANSI},         /* ansi */
188   {"postincrement","++",      0},                 /* old */
189   {"pp",    "++",             DMGL_ANSI},         /* ansi */
190   {"postdecrement","--",      0},                 /* old */
191   {"mm",    "--",             DMGL_ANSI},         /* ansi */
192   {"bit_ior",         "|",              0},                 /* old */
193   {"or",    "|",              DMGL_ANSI},         /* ansi */
194   {"aor",   "|=",             DMGL_ANSI},         /* ansi */
195   {"bit_xor",         "^",              0},                 /* old */
196   {"er",    "^",              DMGL_ANSI},         /* ansi */
197   {"aer",   "^=",             DMGL_ANSI},         /* ansi */
198   {"bit_and",         "&",              0},                 /* old */
199   {"ad",    "&",              DMGL_ANSI},         /* ansi */
200   {"aad",   "&=",             DMGL_ANSI},         /* ansi */
201   {"bit_not",         "~",              0},                 /* old */
202   {"co",    "~",              DMGL_ANSI},         /* ansi */
203   {"call",            "()",             0},                 /* old */
204   {"cl",    "()",             DMGL_ANSI},         /* ansi */
205   {"alshift",         "<<",             0},                 /* old */
206   {"ls",    "<<",             DMGL_ANSI},         /* ansi */
207   {"als",   "<<=",  DMGL_ANSI},         /* ansi */
208   {"arshift",         ">>",             0},                 /* old */
209   {"rs",    ">>",             DMGL_ANSI},         /* ansi */
210   {"ars",   ">>=",  DMGL_ANSI},         /* ansi */
211   {"component",       "->",             0},                 /* old */
212   {"pt",    "->",             DMGL_ANSI},         /* ansi; Lucid C++ form */
213   {"rf",    "->",             DMGL_ANSI},         /* ansi; ARM/GNU form */
214   {"indirect",        "*",              0},                 /* old */
215   {"method_call",  "->()",    0},                 /* old */
216   {"addr",            "&",              0},                 /* old (unary &) */
217   {"array",           "[]",             0},                 /* old */
218   {"vc",    "[]",             DMGL_ANSI},         /* ansi */
219   {"compound",        ", ",             0},                 /* old */
220   {"cm",    ", ",             DMGL_ANSI},         /* ansi */
221   {"cond",            "?:",             0},                 /* old */
222   {"cn",    "?:",             DMGL_ANSI},         /* pseudo-ansi */
223   {"max",   ">?",             0},                 /* old */
224   {"mx",    ">?",             DMGL_ANSI},         /* pseudo-ansi */
225   {"min",   "<?",             0},                 /* old */
226   {"mn",    "<?",             DMGL_ANSI},         /* pseudo-ansi */
227   {"nop",   "",               0},                 /* old (for operator=) */
228   {"rm",    "->*",  DMGL_ANSI},         /* ansi */
229   {"sz",          "sizeof ",    DMGL_ANSI}      /* pseudo-ansi */
230 };
231 
232 /* These values are used to indicate the various type varieties.
233    They are all non-zero so that they can be used as `success'
234    values.  */
235 typedef enum type_kind_t
236 {
237   tk_none,
238   tk_pointer,
239   tk_reference,
240   tk_integral,
241   tk_bool,
242   tk_char,
243   tk_real
244 } type_kind_t;
245 
246 const struct demangler_engine libiberty_demanglers[] =
247 {
248   {
249     NO_DEMANGLING_STYLE_STRING,
250     no_demangling,
251     "Demangling disabled"
252   }
253   ,
254   {
255     AUTO_DEMANGLING_STYLE_STRING,
256       auto_demangling,
257       "Automatic selection based on executable"
258   }
259   ,
260   {
261     GNU_DEMANGLING_STYLE_STRING,
262       gnu_demangling,
263       "GNU (g++) style demangling"
264   }
265   ,
266   {
267     LUCID_DEMANGLING_STYLE_STRING,
268       lucid_demangling,
269       "Lucid (lcc) style demangling"
270   }
271   ,
272   {
273     ARM_DEMANGLING_STYLE_STRING,
274       arm_demangling,
275       "ARM style demangling"
276   }
277   ,
278   {
279     HP_DEMANGLING_STYLE_STRING,
280       hp_demangling,
281       "HP (aCC) style demangling"
282   }
283   ,
284   {
285     EDG_DEMANGLING_STYLE_STRING,
286       edg_demangling,
287       "EDG style demangling"
288   }
289   ,
290   {
291     GNU_V3_DEMANGLING_STYLE_STRING,
292     gnu_v3_demangling,
293     "GNU (g++) V3 ABI-style demangling"
294   }
295   ,
296   {
297     JAVA_DEMANGLING_STYLE_STRING,
298     java_demangling,
299     "Java style demangling"
300   }
301   ,
302   {
303     GNAT_DEMANGLING_STYLE_STRING,
304     gnat_demangling,
305     "GNAT style demangling"
306   }
307   ,
308   {
309     NULL, unknown_demangling, NULL
310   }
311 };
312 
313 #define STRING_EMPTY(str)     ((str) -> b == (str) -> p)
314 #define APPEND_BLANK(str)     {if (!STRING_EMPTY(str)) \
315     string_append(str, " ");}
316 #define LEN_STRING(str)         ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
317 
318 /* The scope separator appropriate for the language being demangled.  */
319 
320 #define SCOPE_STRING(work) ((work->options & DMGL_JAVA) ? "." : "::")
321 
322 #define ARM_VTABLE_STRING "__vtbl__"    /* Lucid/ARM virtual table prefix */
323 #define ARM_VTABLE_STRLEN 8             /* strlen (ARM_VTABLE_STRING) */
324 
325 /* Prototypes for local functions */
326 
327 static void delete_work_stuff (struct work_stuff *);
328 
329 static void delete_non_B_K_work_stuff (struct work_stuff *);
330 
331 static char *mop_up (struct work_stuff *, string *, int);
332 
333 static void squangle_mop_up (struct work_stuff *);
334 
335 static void work_stuff_copy_to_from (struct work_stuff *, struct work_stuff *);
336 
337 #if 0
338 static int
339 demangle_method_args (struct work_stuff *, const char **, string *);
340 #endif
341 
342 static char *
343 internal_cplus_demangle (struct work_stuff *, const char *);
344 
345 static int
346 demangle_template_template_parm (struct work_stuff *work,
347                                  const char **, string *);
348 
349 static int
350 demangle_template (struct work_stuff *work, const char **, string *,
351                    string *, int, int);
352 
353 static int
354 arm_pt (struct work_stuff *, const char *, int, const char **,
355         const char **);
356 
357 static int
358 demangle_class_name (struct work_stuff *, const char **, string *);
359 
360 static int
361 demangle_qualified (struct work_stuff *, const char **, string *,
362                     int, int);
363 
364 static int demangle_class (struct work_stuff *, const char **, string *);
365 
366 static int demangle_fund_type (struct work_stuff *, const char **, string *);
367 
368 static int demangle_signature (struct work_stuff *, const char **, string *);
369 
370 static int demangle_prefix (struct work_stuff *, const char **, string *);
371 
372 static int gnu_special (struct work_stuff *, const char **, string *);
373 
374 static int arm_special (const char **, string *);
375 
376 static void string_need (string *, int);
377 
378 static void string_delete (string *);
379 
380 static void
381 string_init (string *);
382 
383 static void string_clear (string *);
384 
385 #if 0
386 static int string_empty (string *);
387 #endif
388 
389 static void string_append (string *, const char *);
390 
391 static void string_appends (string *, string *);
392 
393 static void string_appendn (string *, const char *, int);
394 
395 static void string_prepend (string *, const char *);
396 
397 static void string_prependn (string *, const char *, int);
398 
399 static void string_append_template_idx (string *, int);
400 
401 static int get_count (const char **, int *);
402 
403 static int consume_count (const char **);
404 
405 static int consume_count_with_underscores (const char**);
406 
407 static int demangle_args (struct work_stuff *, const char **, string *);
408 
409 static int demangle_nested_args (struct work_stuff*, const char**, string*);
410 
411 static int do_type (struct work_stuff *, const char **, string *);
412 
413 static int do_arg (struct work_stuff *, const char **, string *);
414 
415 static int
416 demangle_function_name (struct work_stuff *, const char **, string *,
417                         const char *);
418 
419 static int
420 iterate_demangle_function (struct work_stuff *,
421                            const char **, string *, const char *);
422 
423 static void remember_type (struct work_stuff *, const char *, int);
424 
425 static void remember_Btype (struct work_stuff *, const char *, int, int);
426 
427 static int register_Btype (struct work_stuff *);
428 
429 static void remember_Ktype (struct work_stuff *, const char *, int);
430 
431 static void forget_types (struct work_stuff *);
432 
433 static void forget_B_and_K_types (struct work_stuff *);
434 
435 static void string_prepends (string *, string *);
436 
437 static int
438 demangle_template_value_parm (struct work_stuff*, const char**,
439                               string*, type_kind_t);
440 
441 static int
442 do_hpacc_template_const_value (struct work_stuff *, const char **, string *);
443 
444 static int
445 do_hpacc_template_literal (struct work_stuff *, const char **, string *);
446 
447 static int snarf_numeric_literal (const char **, string *);
448 
449 /* There is a TYPE_QUAL value for each type qualifier.  They can be
450    combined by bitwise-or to form the complete set of qualifiers for a
451    type.  */
452 
453 #define TYPE_UNQUALIFIED   0x0
454 #define TYPE_QUAL_CONST    0x1
455 #define TYPE_QUAL_VOLATILE 0x2
456 #define TYPE_QUAL_RESTRICT 0x4
457 
458 static int code_for_qualifier (int);
459 
460 static const char* qualifier_string (int);
461 
462 static const char* demangle_qualifier (int);
463 
464 static int demangle_expression (struct work_stuff *, const char **, string *,
465                                 type_kind_t);
466 
467 static int
468 demangle_integral_value (struct work_stuff *, const char **, string *);
469 
470 static int
471 demangle_real_value (struct work_stuff *, const char **, string *);
472 
473 static void
474 demangle_arm_hp_template (struct work_stuff *, const char **, int, string *);
475 
476 static void
477 recursively_demangle (struct work_stuff *, const char **, string *, int);
478 
479 /* Translate count to integer, consuming tokens in the process.
480    Conversion terminates on the first non-digit character.
481 
482    Trying to consume something that isn't a count results in no
483    consumption of input and a return of -1.
484 
485    Overflow consumes the rest of the digits, and returns -1.  */
486 
487 static int
consume_count(const char ** type)488 consume_count (const char **type)
489 {
490   int count = 0;
491 
492   if (! ISDIGIT ((unsigned char)**type))
493     return -1;
494 
495   while (ISDIGIT ((unsigned char)**type))
496     {
497       count *= 10;
498 
499       /* Check for overflow.
500            We assume that count is represented using two's-complement;
501            no power of two is divisible by ten, so if an overflow occurs
502            when multiplying by ten, the result will not be a multiple of
503            ten.  */
504       if ((count % 10) != 0)
505           {
506             while (ISDIGIT ((unsigned char) **type))
507               (*type)++;
508             return -1;
509           }
510 
511       count += **type - '0';
512       (*type)++;
513     }
514 
515   if (count < 0)
516     count = -1;
517 
518   return (count);
519 }
520 
521 
522 /* Like consume_count, but for counts that are preceded and followed
523    by '_' if they are greater than 10.  Also, -1 is returned for
524    failure, since 0 can be a valid value.  */
525 
526 static int
consume_count_with_underscores(const char ** mangled)527 consume_count_with_underscores (const char **mangled)
528 {
529   int idx;
530 
531   if (**mangled == '_')
532     {
533       (*mangled)++;
534       if (!ISDIGIT ((unsigned char)**mangled))
535           return -1;
536 
537       idx = consume_count (mangled);
538       if (**mangled != '_')
539           /* The trailing underscore was missing. */
540           return -1;
541 
542       (*mangled)++;
543     }
544   else
545     {
546       if (**mangled < '0' || **mangled > '9')
547           return -1;
548 
549       idx = **mangled - '0';
550       (*mangled)++;
551     }
552 
553   return idx;
554 }
555 
556 /* C is the code for a type-qualifier.  Return the TYPE_QUAL
557    corresponding to this qualifier.  */
558 
559 static int
code_for_qualifier(int c)560 code_for_qualifier (int c)
561 {
562   switch (c)
563     {
564     case 'C':
565       return TYPE_QUAL_CONST;
566 
567     case 'V':
568       return TYPE_QUAL_VOLATILE;
569 
570     case 'u':
571       return TYPE_QUAL_RESTRICT;
572 
573     default:
574       break;
575     }
576 
577   /* C was an invalid qualifier.  */
578   abort ();
579 }
580 
581 /* Return the string corresponding to the qualifiers given by
582    TYPE_QUALS.  */
583 
584 static const char*
qualifier_string(int type_quals)585 qualifier_string (int type_quals)
586 {
587   switch (type_quals)
588     {
589     case TYPE_UNQUALIFIED:
590       return "";
591 
592     case TYPE_QUAL_CONST:
593       return "const";
594 
595     case TYPE_QUAL_VOLATILE:
596       return "volatile";
597 
598     case TYPE_QUAL_RESTRICT:
599       return "__restrict";
600 
601     case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
602       return "const volatile";
603 
604     case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
605       return "const __restrict";
606 
607     case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
608       return "volatile __restrict";
609 
610     case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
611       return "const volatile __restrict";
612 
613     default:
614       break;
615     }
616 
617   /* TYPE_QUALS was an invalid qualifier set.  */
618   abort ();
619 }
620 
621 /* C is the code for a type-qualifier.  Return the string
622    corresponding to this qualifier.  This function should only be
623    called with a valid qualifier code.  */
624 
625 static const char*
demangle_qualifier(int c)626 demangle_qualifier (int c)
627 {
628   return qualifier_string (code_for_qualifier (c));
629 }
630 
631 int
cplus_demangle_opname(const char * opname,char * result,int options)632 cplus_demangle_opname (const char *opname, char *result, int options)
633 {
634   int len, len1, ret;
635   string type;
636   struct work_stuff work[1];
637   const char *tem;
638 
639   len = strlen(opname);
640   result[0] = '\0';
641   ret = 0;
642   memset ((char *) work, 0, sizeof (work));
643   work->options = options;
644 
645   if (opname[0] == '_' && opname[1] == '_'
646       && opname[2] == 'o' && opname[3] == 'p')
647     {
648       /* ANSI.  */
649       /* type conversion operator.  */
650       tem = opname + 4;
651       if (do_type (work, &tem, &type))
652           {
653             strcat (result, "operator ");
654             strncat (result, type.b, type.p - type.b);
655             string_delete (&type);
656             ret = 1;
657           }
658     }
659   else if (opname[0] == '_' && opname[1] == '_'
660              && ISLOWER((unsigned char)opname[2])
661              && ISLOWER((unsigned char)opname[3]))
662     {
663       if (opname[4] == '\0')
664           {
665             /* Operator.  */
666             size_t i;
667             for (i = 0; i < ARRAY_SIZE (optable); i++)
668               {
669                 if (strlen (optable[i].in) == 2
670                       && memcmp (optable[i].in, opname + 2, 2) == 0)
671                     {
672                       strcat (result, "operator");
673                       strcat (result, optable[i].out);
674                       ret = 1;
675                       break;
676                     }
677               }
678           }
679       else
680           {
681             if (opname[2] == 'a' && opname[5] == '\0')
682               {
683                 /* Assignment.  */
684                 size_t i;
685                 for (i = 0; i < ARRAY_SIZE (optable); i++)
686                     {
687                       if (strlen (optable[i].in) == 3
688                           && memcmp (optable[i].in, opname + 2, 3) == 0)
689                         {
690                           strcat (result, "operator");
691                           strcat (result, optable[i].out);
692                           ret = 1;
693                           break;
694                         }
695                     }
696               }
697           }
698     }
699   else if (len >= 3
700              && opname[0] == 'o'
701              && opname[1] == 'p'
702              && strchr (cplus_markers, opname[2]) != NULL)
703     {
704       /* see if it's an assignment expression */
705       if (len >= 10 /* op$assign_ */
706             && memcmp (opname + 3, "assign_", 7) == 0)
707           {
708             size_t i;
709             for (i = 0; i < ARRAY_SIZE (optable); i++)
710               {
711                 len1 = len - 10;
712                 if ((int) strlen (optable[i].in) == len1
713                       && memcmp (optable[i].in, opname + 10, len1) == 0)
714                     {
715                       strcat (result, "operator");
716                       strcat (result, optable[i].out);
717                       strcat (result, "=");
718                       ret = 1;
719                       break;
720                     }
721               }
722           }
723       else
724           {
725             size_t i;
726             for (i = 0; i < ARRAY_SIZE (optable); i++)
727               {
728                 len1 = len - 3;
729                 if ((int) strlen (optable[i].in) == len1
730                       && memcmp (optable[i].in, opname + 3, len1) == 0)
731                     {
732                       strcat (result, "operator");
733                       strcat (result, optable[i].out);
734                       ret = 1;
735                       break;
736                     }
737               }
738           }
739     }
740   else if (len >= 5 && memcmp (opname, "type", 4) == 0
741              && strchr (cplus_markers, opname[4]) != NULL)
742     {
743       /* type conversion operator */
744       tem = opname + 5;
745       if (do_type (work, &tem, &type))
746           {
747             strcat (result, "operator ");
748             strncat (result, type.b, type.p - type.b);
749             string_delete (&type);
750             ret = 1;
751           }
752     }
753   squangle_mop_up (work);
754   return ret;
755 
756 }
757 
758 /* Takes operator name as e.g. "++" and returns mangled
759    operator name (e.g. "postincrement_expr"), or NULL if not found.
760 
761    If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
762    if OPTIONS & DMGL_ANSI == 0, return the old GNU name.  */
763 
764 const char *
cplus_mangle_opname(const char * opname,int options)765 cplus_mangle_opname (const char *opname, int options)
766 {
767   size_t i;
768   int len;
769 
770   len = strlen (opname);
771   for (i = 0; i < ARRAY_SIZE (optable); i++)
772     {
773       if ((int) strlen (optable[i].out) == len
774             && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
775             && memcmp (optable[i].out, opname, len) == 0)
776           return optable[i].in;
777     }
778   return (0);
779 }
780 
781 /* Add a routine to set the demangling style to be sure it is valid and
782    allow for any demangler initialization that maybe necessary. */
783 
784 enum demangling_styles
cplus_demangle_set_style(enum demangling_styles style)785 cplus_demangle_set_style (enum demangling_styles style)
786 {
787   const struct demangler_engine *demangler = libiberty_demanglers;
788 
789   for (; demangler->demangling_style != unknown_demangling; ++demangler)
790     if (style == demangler->demangling_style)
791       {
792           current_demangling_style = style;
793           return current_demangling_style;
794       }
795 
796   return unknown_demangling;
797 }
798 
799 /* Do string name to style translation */
800 
801 enum demangling_styles
cplus_demangle_name_to_style(const char * name)802 cplus_demangle_name_to_style (const char *name)
803 {
804   const struct demangler_engine *demangler = libiberty_demanglers;
805 
806   for (; demangler->demangling_style != unknown_demangling; ++demangler)
807     if (strcmp (name, demangler->demangling_style_name) == 0)
808       return demangler->demangling_style;
809 
810   return unknown_demangling;
811 }
812 
813 /* char *cplus_demangle (const char *mangled, int options)
814 
815    If MANGLED is a mangled function name produced by GNU C++, then
816    a pointer to a @code{malloc}ed string giving a C++ representation
817    of the name will be returned; otherwise NULL will be returned.
818    It is the caller's responsibility to free the string which
819    is returned.
820 
821    The OPTIONS arg may contain one or more of the following bits:
822 
823           DMGL_ANSI ANSI qualifiers such as `const' and `void' are
824                               included.
825           DMGL_PARAMS         Function parameters are included.
826 
827    For example,
828 
829    cplus_demangle ("foo__1Ai", DMGL_PARAMS)                 => "A::foo(int)"
830    cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI)     => "A::foo(int)"
831    cplus_demangle ("foo__1Ai", 0)                           => "A::foo"
832 
833    cplus_demangle ("foo__1Afe", DMGL_PARAMS)                => "A::foo(float,...)"
834    cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
835    cplus_demangle ("foo__1Afe", 0)                          => "A::foo"
836 
837    Note that any leading underscores, or other such characters prepended by
838    the compilation system, are presumed to have already been stripped from
839    MANGLED.  */
840 
841 char *
cplus_demangle(const char * mangled,int options)842 cplus_demangle (const char *mangled, int options)
843 {
844   char *ret;
845   struct work_stuff work[1];
846 
847   if (current_demangling_style == no_demangling)
848     return xstrdup (mangled);
849 
850   memset ((char *) work, 0, sizeof (work));
851   work->options = options;
852   if ((work->options & DMGL_STYLE_MASK) == 0)
853     work->options |= (int) current_demangling_style & DMGL_STYLE_MASK;
854 
855   /* The V3 ABI demangling is implemented elsewhere.  */
856   if (GNU_V3_DEMANGLING || AUTO_DEMANGLING)
857     {
858       ret = cplus_demangle_v3 (mangled, work->options);
859       if (ret || GNU_V3_DEMANGLING)
860           return ret;
861     }
862 
863   if (JAVA_DEMANGLING)
864     {
865       ret = java_demangle_v3 (mangled);
866       if (ret)
867         return ret;
868     }
869 
870   if (GNAT_DEMANGLING)
871     return ada_demangle (mangled, options);
872 
873   ret = internal_cplus_demangle (work, mangled);
874   squangle_mop_up (work);
875   return (ret);
876 }
877 
878 /* Demangle ada names.  The encoding is documented in gcc/ada/exp_dbug.ads.  */
879 
880 char *
ada_demangle(const char * mangled,int option ATTRIBUTE_UNUSED)881 ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
882 {
883   int len0;
884   const char* p;
885   char *d;
886   char *demangled;
887 
888   /* Discard leading _ada_, which is used for library level subprograms.  */
889   if (strncmp (mangled, "_ada_", 5) == 0)
890     mangled += 5;
891 
892   /* All ada unit names are lower-case.  */
893   if (!ISLOWER (mangled[0]))
894     goto unknown;
895 
896   /* Most of the demangling will trivially remove chars.  Operator names
897      may add one char but because they are always preceeded by '__' which is
898      replaced by '.', they eventually never expand the size.
899      A few special names such as '___elabs' add a few chars (at most 7), but
900      they occur only once.  */
901   len0 = strlen (mangled) + 7 + 1;
902   demangled = XNEWVEC (char, len0);
903 
904   d = demangled;
905   p = mangled;
906   while (1)
907     {
908       /* An entity names is expected.  */
909       if (ISLOWER (*p))
910         {
911           /* An identifier, which is always lower case.  */
912           do
913             *d++ = *p++;
914           while (ISLOWER(*p) || ISDIGIT (*p)
915                  || (p[0] == '_' && (ISLOWER (p[1]) || ISDIGIT (p[1]))));
916         }
917       else if (p[0] == 'O')
918         {
919           /* An operator name.  */
920           static const char * const operators[][2] =
921             {{"Oabs", "abs"},  {"Oand", "and"},    {"Omod", "mod"},
922              {"Onot", "not"},  {"Oor", "or"},      {"Orem", "rem"},
923              {"Oxor", "xor"},  {"Oeq", "="},       {"One", "/="},
924              {"Olt", "<"},     {"Ole", "<="},      {"Ogt", ">"},
925              {"Oge", ">="},    {"Oadd", "+"},      {"Osubtract", "-"},
926              {"Oconcat", "&"}, {"Omultiply", "*"}, {"Odivide", "/"},
927              {"Oexpon", "**"}, {NULL, NULL}};
928           int k;
929 
930           for (k = 0; operators[k][0] != NULL; k++)
931             {
932               size_t slen = strlen (operators[k][0]);
933               if (strncmp (p, operators[k][0], slen) == 0)
934                 {
935                   p += slen;
936                   slen = strlen (operators[k][1]);
937                   *d++ = '"';
938                   memcpy (d, operators[k][1], slen);
939                   d += slen;
940                   *d++ = '"';
941                   break;
942                 }
943             }
944           /* Operator not found.  */
945           if (operators[k][0] == NULL)
946             goto unknown;
947         }
948       else
949         {
950           /* Not a GNAT encoding.  */
951           goto unknown;
952         }
953 
954       /* The name can be directly followed by some uppercase letters.  */
955       if (p[0] == 'T' && p[1] == 'K')
956         {
957           /* Task stuff.  */
958           if (p[2] == 'B' && p[3] == 0)
959             {
960               /* Subprogram for task body.  */
961               break;
962             }
963           else if (p[2] == '_' && p[3] == '_')
964             {
965               /* Inner declarations in a task.  */
966               p += 4;
967               *d++ = '.';
968               continue;
969             }
970           else
971             goto unknown;
972         }
973       if (p[0] == 'E' && p[1] == 0)
974         {
975           /* Exception name.  */
976           goto unknown;
977         }
978       if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0)
979         {
980           /* Protected type subprogram.  */
981           break;
982         }
983       if ((*p == 'N' || *p == 'S') && p[1] == 0)
984         {
985           /* Enumerated type name table.  */
986           goto unknown;
987         }
988       if (p[0] == 'X')
989         {
990           /* Body nested.  */
991           p++;
992           while (p[0] == 'n' || p[0] == 'b')
993             p++;
994         }
995       if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0))
996         {
997           /* Stream operations.  */
998           const char *name;
999           switch (p[1])
1000             {
1001             case 'R':
1002               name = "'Read";
1003               break;
1004             case 'W':
1005               name = "'Write";
1006               break;
1007             case 'I':
1008               name = "'Input";
1009               break;
1010             case 'O':
1011               name = "'Output";
1012               break;
1013             default:
1014               goto unknown;
1015             }
1016           p += 2;
1017           strcpy (d, name);
1018           d += strlen (name);
1019         }
1020       else if (p[0] == 'D')
1021         {
1022           /* Controlled type operation.  */
1023           const char *name;
1024           switch (p[1])
1025             {
1026             case 'F':
1027               name = ".Finalize";
1028               break;
1029             case 'A':
1030               name = ".Adjust";
1031               break;
1032             default:
1033               goto unknown;
1034             }
1035           strcpy (d, name);
1036           d += strlen (name);
1037           break;
1038         }
1039 
1040       if (p[0] == '_')
1041         {
1042           /* Separator.  */
1043           if (p[1] == '_')
1044             {
1045               /* Standard separator.  Handled first.  */
1046               p += 2;
1047 
1048               if (ISDIGIT (*p))
1049                 {
1050                   /* Overloading number.  */
1051                   do
1052                     p++;
1053                   while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1])));
1054                   if (*p == 'X')
1055                     {
1056                       p++;
1057                       while (p[0] == 'n' || p[0] == 'b')
1058                         p++;
1059                     }
1060                 }
1061               else if (p[0] == '_' && p[1] != '_')
1062                 {
1063                   /* Special names.  */
1064                   static const char * const special[][2] = {
1065                     { "_elabb", "'Elab_Body" },
1066                     { "_elabs", "'Elab_Spec" },
1067                     { "_size", "'Size" },
1068                     { "_alignment", "'Alignment" },
1069                     { "_assign", ".\":=\"" },
1070                     { NULL, NULL }
1071                   };
1072                   int k;
1073 
1074                   for (k = 0; special[k][0] != NULL; k++)
1075                     {
1076                       size_t slen = strlen (special[k][0]);
1077                       if (strncmp (p, special[k][0], slen) == 0)
1078                         {
1079                           p += slen;
1080                           slen = strlen (special[k][1]);
1081                           memcpy (d, special[k][1], slen);
1082                           d += slen;
1083                           break;
1084                         }
1085                     }
1086                   if (special[k][0] != NULL)
1087                     break;
1088                   else
1089                     goto unknown;
1090                 }
1091               else
1092                 {
1093                   *d++ = '.';
1094                   continue;
1095                 }
1096             }
1097           else if (p[1] == 'B' || p[1] == 'E')
1098             {
1099               /* Entry Body or barrier Evaluation.  */
1100               p += 2;
1101               while (ISDIGIT (*p))
1102                 p++;
1103               if (p[0] == 's' && p[1] == 0)
1104                 break;
1105               else
1106                 goto unknown;
1107             }
1108           else
1109             goto unknown;
1110         }
1111 
1112       if (p[0] == '.' && ISDIGIT (p[1]))
1113         {
1114           /* Nested subprogram.  */
1115           p += 2;
1116           while (ISDIGIT (*p))
1117             p++;
1118         }
1119       if (*p == 0)
1120         {
1121           /* End of mangled name.  */
1122           break;
1123         }
1124       else
1125         goto unknown;
1126     }
1127   *d = 0;
1128   return demangled;
1129 
1130  unknown:
1131   len0 = strlen (mangled);
1132   demangled = XNEWVEC (char, len0 + 3);
1133 
1134   if (mangled[0] == '<')
1135      strcpy (demangled, mangled);
1136   else
1137     sprintf (demangled, "<%s>", mangled);
1138 
1139   return demangled;
1140 }
1141 
1142 /* This function performs most of what cplus_demangle use to do, but
1143    to be able to demangle a name with a B, K or n code, we need to
1144    have a longer term memory of what types have been seen. The original
1145    now initializes and cleans up the squangle code info, while internal
1146    calls go directly to this routine to avoid resetting that info. */
1147 
1148 static char *
internal_cplus_demangle(struct work_stuff * work,const char * mangled)1149 internal_cplus_demangle (struct work_stuff *work, const char *mangled)
1150 {
1151 
1152   string decl;
1153   int success = 0;
1154   char *demangled = NULL;
1155   int s1, s2, s3, s4;
1156   s1 = work->constructor;
1157   s2 = work->destructor;
1158   s3 = work->static_type;
1159   s4 = work->type_quals;
1160   work->constructor = work->destructor = 0;
1161   work->type_quals = TYPE_UNQUALIFIED;
1162   work->dllimported = 0;
1163 
1164   if ((mangled != NULL) && (*mangled != '\0'))
1165     {
1166       string_init (&decl);
1167 
1168       /* First check to see if gnu style demangling is active and if the
1169            string to be demangled contains a CPLUS_MARKER.  If so, attempt to
1170            recognize one of the gnu special forms rather than looking for a
1171            standard prefix.  In particular, don't worry about whether there
1172            is a "__" string in the mangled string.  Consider "_$_5__foo" for
1173            example.  */
1174 
1175       if ((AUTO_DEMANGLING || GNU_DEMANGLING))
1176           {
1177             success = gnu_special (work, &mangled, &decl);
1178           }
1179       if (!success)
1180           {
1181             success = demangle_prefix (work, &mangled, &decl);
1182           }
1183       if (success && (*mangled != '\0'))
1184           {
1185             success = demangle_signature (work, &mangled, &decl);
1186           }
1187       if (work->constructor == 2)
1188         {
1189           string_prepend (&decl, "global constructors keyed to ");
1190           work->constructor = 0;
1191         }
1192       else if (work->destructor == 2)
1193         {
1194           string_prepend (&decl, "global destructors keyed to ");
1195           work->destructor = 0;
1196         }
1197       else if (work->dllimported == 1)
1198         {
1199           string_prepend (&decl, "import stub for ");
1200           work->dllimported = 0;
1201         }
1202       demangled = mop_up (work, &decl, success);
1203     }
1204   work->constructor = s1;
1205   work->destructor = s2;
1206   work->static_type = s3;
1207   work->type_quals = s4;
1208   return demangled;
1209 }
1210 
1211 
1212 /* Clear out and squangling related storage */
1213 static void
squangle_mop_up(struct work_stuff * work)1214 squangle_mop_up (struct work_stuff *work)
1215 {
1216   /* clean up the B and K type mangling types. */
1217   forget_B_and_K_types (work);
1218   if (work -> btypevec != NULL)
1219     {
1220       free ((char *) work -> btypevec);
1221     }
1222   if (work -> ktypevec != NULL)
1223     {
1224       free ((char *) work -> ktypevec);
1225     }
1226 }
1227 
1228 
1229 /* Copy the work state and storage.  */
1230 
1231 static void
work_stuff_copy_to_from(struct work_stuff * to,struct work_stuff * from)1232 work_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from)
1233 {
1234   int i;
1235 
1236   delete_work_stuff (to);
1237 
1238   /* Shallow-copy scalars.  */
1239   memcpy (to, from, sizeof (*to));
1240 
1241   /* Deep-copy dynamic storage.  */
1242   if (from->typevec_size)
1243     to->typevec = XNEWVEC (char *, from->typevec_size);
1244 
1245   for (i = 0; i < from->ntypes; i++)
1246     {
1247       int len = strlen (from->typevec[i]) + 1;
1248 
1249       to->typevec[i] = XNEWVEC (char, len);
1250       memcpy (to->typevec[i], from->typevec[i], len);
1251     }
1252 
1253   if (from->ksize)
1254     to->ktypevec = XNEWVEC (char *, from->ksize);
1255 
1256   for (i = 0; i < from->numk; i++)
1257     {
1258       int len = strlen (from->ktypevec[i]) + 1;
1259 
1260       to->ktypevec[i] = XNEWVEC (char, len);
1261       memcpy (to->ktypevec[i], from->ktypevec[i], len);
1262     }
1263 
1264   if (from->bsize)
1265     to->btypevec = XNEWVEC (char *, from->bsize);
1266 
1267   for (i = 0; i < from->numb; i++)
1268     {
1269       int len = strlen (from->btypevec[i]) + 1;
1270 
1271       to->btypevec[i] = XNEWVEC (char , len);
1272       memcpy (to->btypevec[i], from->btypevec[i], len);
1273     }
1274 
1275   if (from->ntmpl_args)
1276     to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args);
1277 
1278   for (i = 0; i < from->ntmpl_args; i++)
1279     {
1280       int len = strlen (from->tmpl_argvec[i]) + 1;
1281 
1282       to->tmpl_argvec[i] = XNEWVEC (char, len);
1283       memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len);
1284     }
1285 
1286   if (from->previous_argument)
1287     {
1288       to->previous_argument = XNEW (string);
1289       string_init (to->previous_argument);
1290       string_appends (to->previous_argument, from->previous_argument);
1291     }
1292 }
1293 
1294 
1295 /* Delete dynamic stuff in work_stuff that is not to be re-used.  */
1296 
1297 static void
delete_non_B_K_work_stuff(struct work_stuff * work)1298 delete_non_B_K_work_stuff (struct work_stuff *work)
1299 {
1300   /* Discard the remembered types, if any.  */
1301 
1302   forget_types (work);
1303   if (work -> typevec != NULL)
1304     {
1305       free ((char *) work -> typevec);
1306       work -> typevec = NULL;
1307       work -> typevec_size = 0;
1308     }
1309   if (work->tmpl_argvec)
1310     {
1311       int i;
1312 
1313       for (i = 0; i < work->ntmpl_args; i++)
1314           free ((char*) work->tmpl_argvec[i]);
1315 
1316       free ((char*) work->tmpl_argvec);
1317       work->tmpl_argvec = NULL;
1318     }
1319   if (work->previous_argument)
1320     {
1321       string_delete (work->previous_argument);
1322       free ((char*) work->previous_argument);
1323       work->previous_argument = NULL;
1324     }
1325 }
1326 
1327 
1328 /* Delete all dynamic storage in work_stuff.  */
1329 static void
delete_work_stuff(struct work_stuff * work)1330 delete_work_stuff (struct work_stuff *work)
1331 {
1332   delete_non_B_K_work_stuff (work);
1333   squangle_mop_up (work);
1334 }
1335 
1336 
1337 /* Clear out any mangled storage */
1338 
1339 static char *
mop_up(struct work_stuff * work,string * declp,int success)1340 mop_up (struct work_stuff *work, string *declp, int success)
1341 {
1342   char *demangled = NULL;
1343 
1344   delete_non_B_K_work_stuff (work);
1345 
1346   /* If demangling was successful, ensure that the demangled string is null
1347      terminated and return it.  Otherwise, free the demangling decl.  */
1348 
1349   if (!success)
1350     {
1351       string_delete (declp);
1352     }
1353   else
1354     {
1355       string_appendn (declp, "", 1);
1356       demangled = declp->b;
1357     }
1358   return (demangled);
1359 }
1360 
1361 /*
1362 
1363 LOCAL FUNCTION
1364 
1365           demangle_signature -- demangle the signature part of a mangled name
1366 
1367 SYNOPSIS
1368 
1369           static int
1370           demangle_signature (struct work_stuff *work, const char **mangled,
1371                                   string *declp);
1372 
1373 DESCRIPTION
1374 
1375           Consume and demangle the signature portion of the mangled name.
1376 
1377           DECLP is the string where demangled output is being built.  At
1378           entry it contains the demangled root name from the mangled name
1379           prefix.  I.E. either a demangled operator name or the root function
1380           name.  In some special cases, it may contain nothing.
1381 
1382           *MANGLED points to the current unconsumed location in the mangled
1383           name.  As tokens are consumed and demangling is performed, the
1384           pointer is updated to continuously point at the next token to
1385           be consumed.
1386 
1387           Demangling GNU style mangled names is nasty because there is no
1388           explicit token that marks the start of the outermost function
1389           argument list.  */
1390 
1391 static int
demangle_signature(struct work_stuff * work,const char ** mangled,string * declp)1392 demangle_signature (struct work_stuff *work,
1393                     const char **mangled, string *declp)
1394 {
1395   int success = 1;
1396   int func_done = 0;
1397   int expect_func = 0;
1398   int expect_return_type = 0;
1399   const char *oldmangled = NULL;
1400   string trawname;
1401   string tname;
1402 
1403   while (success && (**mangled != '\0'))
1404     {
1405       switch (**mangled)
1406           {
1407           case 'Q':
1408             oldmangled = *mangled;
1409             success = demangle_qualified (work, mangled, declp, 1, 0);
1410             if (success)
1411               remember_type (work, oldmangled, *mangled - oldmangled);
1412             if (AUTO_DEMANGLING || GNU_DEMANGLING)
1413               expect_func = 1;
1414             oldmangled = NULL;
1415             break;
1416 
1417         case 'K':
1418             oldmangled = *mangled;
1419             success = demangle_qualified (work, mangled, declp, 1, 0);
1420             if (AUTO_DEMANGLING || GNU_DEMANGLING)
1421               {
1422                 expect_func = 1;
1423               }
1424             oldmangled = NULL;
1425             break;
1426 
1427           case 'S':
1428             /* Static member function */
1429             if (oldmangled == NULL)
1430               {
1431                 oldmangled = *mangled;
1432               }
1433             (*mangled)++;
1434             work -> static_type = 1;
1435             break;
1436 
1437           case 'C':
1438           case 'V':
1439           case 'u':
1440             work->type_quals |= code_for_qualifier (**mangled);
1441 
1442             /* a qualified member function */
1443             if (oldmangled == NULL)
1444               oldmangled = *mangled;
1445             (*mangled)++;
1446             break;
1447 
1448           case 'L':
1449             /* Local class name follows after "Lnnn_" */
1450             if (HP_DEMANGLING)
1451               {
1452                 while (**mangled && (**mangled != '_'))
1453                     (*mangled)++;
1454                 if (!**mangled)
1455                     success = 0;
1456                 else
1457                     (*mangled)++;
1458               }
1459             else
1460               success = 0;
1461             break;
1462 
1463           case '0': case '1': case '2': case '3': case '4':
1464           case '5': case '6': case '7': case '8': case '9':
1465             if (oldmangled == NULL)
1466               {
1467                 oldmangled = *mangled;
1468               }
1469           work->temp_start = -1; /* uppermost call to demangle_class */
1470             success = demangle_class (work, mangled, declp);
1471             if (success)
1472               {
1473                 remember_type (work, oldmangled, *mangled - oldmangled);
1474               }
1475             if (AUTO_DEMANGLING || GNU_DEMANGLING || EDG_DEMANGLING)
1476               {
1477               /* EDG and others will have the "F", so we let the loop cycle
1478                  if we are looking at one. */
1479               if (**mangled != 'F')
1480                  expect_func = 1;
1481               }
1482             oldmangled = NULL;
1483             break;
1484 
1485           case 'B':
1486             {
1487               string s;
1488               success = do_type (work, mangled, &s);
1489               if (success)
1490                 {
1491                     string_append (&s, SCOPE_STRING (work));
1492                     string_prepends (declp, &s);
1493                     string_delete (&s);
1494                 }
1495               oldmangled = NULL;
1496               expect_func = 1;
1497             }
1498             break;
1499 
1500           case 'F':
1501             /* Function */
1502             /* ARM/HP style demangling includes a specific 'F' character after
1503                the class name.  For GNU style, it is just implied.  So we can
1504                safely just consume any 'F' at this point and be compatible
1505                with either style.  */
1506 
1507             oldmangled = NULL;
1508             func_done = 1;
1509             (*mangled)++;
1510 
1511             /* For lucid/ARM/HP style we have to forget any types we might
1512                have remembered up to this point, since they were not argument
1513                types.  GNU style considers all types seen as available for
1514                back references.  See comment in demangle_args() */
1515 
1516             if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
1517               {
1518                 forget_types (work);
1519               }
1520             success = demangle_args (work, mangled, declp);
1521             /* After picking off the function args, we expect to either
1522                find the function return type (preceded by an '_') or the
1523                end of the string. */
1524             if (success && (AUTO_DEMANGLING || EDG_DEMANGLING) && **mangled == '_')
1525               {
1526                 ++(*mangled);
1527               /* At this level, we do not care about the return type. */
1528               success = do_type (work, mangled, &tname);
1529               string_delete (&tname);
1530             }
1531 
1532             break;
1533 
1534           case 't':
1535             /* G++ Template */
1536             string_init(&trawname);
1537             string_init(&tname);
1538             if (oldmangled == NULL)
1539               {
1540                 oldmangled = *mangled;
1541               }
1542             success = demangle_template (work, mangled, &tname,
1543                                                &trawname, 1, 1);
1544             if (success)
1545               {
1546                 remember_type (work, oldmangled, *mangled - oldmangled);
1547               }
1548             string_append (&tname, SCOPE_STRING (work));
1549 
1550             string_prepends(declp, &tname);
1551             if (work -> destructor & 1)
1552               {
1553                 string_prepend (&trawname, "~");
1554                 string_appends (declp, &trawname);
1555                 work->destructor -= 1;
1556               }
1557             if ((work->constructor & 1) || (work->destructor & 1))
1558               {
1559                 string_appends (declp, &trawname);
1560                 work->constructor -= 1;
1561               }
1562             string_delete(&trawname);
1563             string_delete(&tname);
1564             oldmangled = NULL;
1565             expect_func = 1;
1566             break;
1567 
1568           case '_':
1569             if ((AUTO_DEMANGLING || GNU_DEMANGLING) && expect_return_type)
1570               {
1571                 /* Read the return type. */
1572                 string return_type;
1573 
1574                 (*mangled)++;
1575                 success = do_type (work, mangled, &return_type);
1576                 APPEND_BLANK (&return_type);
1577 
1578                 string_prepends (declp, &return_type);
1579                 string_delete (&return_type);
1580                 break;
1581               }
1582             else
1583               /* At the outermost level, we cannot have a return type specified,
1584                  so if we run into another '_' at this point we are dealing with
1585                  a mangled name that is either bogus, or has been mangled by
1586                  some algorithm we don't know how to deal with.  So just
1587                  reject the entire demangling.  */
1588             /* However, "_nnn" is an expected suffix for alternate entry point
1589                numbered nnn for a function, with HP aCC, so skip over that
1590                without reporting failure. pai/1997-09-04 */
1591             if (HP_DEMANGLING)
1592               {
1593                 (*mangled)++;
1594                 while (**mangled && ISDIGIT ((unsigned char)**mangled))
1595                   (*mangled)++;
1596               }
1597             else
1598                 success = 0;
1599             break;
1600 
1601           case 'H':
1602             if (AUTO_DEMANGLING || GNU_DEMANGLING)
1603               {
1604                 /* A G++ template function.  Read the template arguments. */
1605                 success = demangle_template (work, mangled, declp, 0, 0,
1606                                                      0);
1607                 if (!(work->constructor & 1))
1608                     expect_return_type = 1;
1609                 (*mangled)++;
1610                 break;
1611               }
1612             else
1613               /* fall through */
1614               {;}
1615 
1616           default:
1617             if (AUTO_DEMANGLING || GNU_DEMANGLING)
1618               {
1619                 /* Assume we have stumbled onto the first outermost function
1620                      argument token, and start processing args.  */
1621                 func_done = 1;
1622                 success = demangle_args (work, mangled, declp);
1623               }
1624             else
1625               {
1626                 /* Non-GNU demanglers use a specific token to mark the start
1627                      of the outermost function argument tokens.  Typically 'F',
1628                      for ARM/HP-demangling, for example.  So if we find something
1629                      we are not prepared for, it must be an error.  */
1630                 success = 0;
1631               }
1632             break;
1633           }
1634       /*
1635           if (AUTO_DEMANGLING || GNU_DEMANGLING)
1636           */
1637       {
1638           if (success && expect_func)
1639             {
1640               func_done = 1;
1641               if (LUCID_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING)
1642                 {
1643                   forget_types (work);
1644                 }
1645               success = demangle_args (work, mangled, declp);
1646               /* Since template include the mangling of their return types,
1647                  we must set expect_func to 0 so that we don't try do
1648                  demangle more arguments the next time we get here.  */
1649               expect_func = 0;
1650             }
1651       }
1652     }
1653   if (success && !func_done)
1654     {
1655       if (AUTO_DEMANGLING || GNU_DEMANGLING)
1656           {
1657             /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
1658                bar__3fooi is 'foo::bar(int)'.  We get here when we find the
1659                first case, and need to ensure that the '(void)' gets added to
1660                the current declp.  Note that with ARM/HP, the first case
1661                represents the name of a static data member 'foo::bar',
1662                which is in the current declp, so we leave it alone.  */
1663             success = demangle_args (work, mangled, declp);
1664           }
1665     }
1666   if (success && PRINT_ARG_TYPES)
1667     {
1668       if (work->static_type)
1669           string_append (declp, " static");
1670       if (work->type_quals != TYPE_UNQUALIFIED)
1671           {
1672             APPEND_BLANK (declp);
1673             string_append (declp, qualifier_string (work->type_quals));
1674           }
1675     }
1676 
1677   return (success);
1678 }
1679 
1680 #if 0
1681 
1682 static int
1683 demangle_method_args (struct work_stuff *work, const char **mangled,
1684                       string *declp)
1685 {
1686   int success = 0;
1687 
1688   if (work -> static_type)
1689     {
1690       string_append (declp, *mangled + 1);
1691       *mangled += strlen (*mangled);
1692       success = 1;
1693     }
1694   else
1695     {
1696       success = demangle_args (work, mangled, declp);
1697     }
1698   return (success);
1699 }
1700 
1701 #endif
1702 
1703 static int
demangle_template_template_parm(struct work_stuff * work,const char ** mangled,string * tname)1704 demangle_template_template_parm (struct work_stuff *work,
1705                                  const char **mangled, string *tname)
1706 {
1707   int i;
1708   int r;
1709   int need_comma = 0;
1710   int success = 1;
1711   string temp;
1712 
1713   string_append (tname, "template <");
1714   /* get size of template parameter list */
1715   if (get_count (mangled, &r))
1716     {
1717       for (i = 0; i < r; i++)
1718           {
1719             if (need_comma)
1720               {
1721                 string_append (tname, ", ");
1722               }
1723 
1724               /* Z for type parameters */
1725               if (**mangled == 'Z')
1726                 {
1727                     (*mangled)++;
1728                     string_append (tname, "class");
1729                 }
1730                 /* z for template parameters */
1731               else if (**mangled == 'z')
1732                 {
1733                     (*mangled)++;
1734                     success =
1735                       demangle_template_template_parm (work, mangled, tname);
1736                     if (!success)
1737                       {
1738                         break;
1739                       }
1740                 }
1741               else
1742                 {
1743                     /* temp is initialized in do_type */
1744                     success = do_type (work, mangled, &temp);
1745                     if (success)
1746                       {
1747                         string_appends (tname, &temp);
1748                       }
1749                     string_delete(&temp);
1750                     if (!success)
1751                       {
1752                         break;
1753                       }
1754                 }
1755             need_comma = 1;
1756           }
1757 
1758     }
1759   if (tname->p[-1] == '>')
1760     string_append (tname, " ");
1761   string_append (tname, "> class");
1762   return (success);
1763 }
1764 
1765 static int
demangle_expression(struct work_stuff * work,const char ** mangled,string * s,type_kind_t tk)1766 demangle_expression (struct work_stuff *work, const char **mangled,
1767                      string *s, type_kind_t tk)
1768 {
1769   int need_operator = 0;
1770   int success;
1771 
1772   success = 1;
1773   string_appendn (s, "(", 1);
1774   (*mangled)++;
1775   while (success && **mangled != 'W' && **mangled != '\0')
1776     {
1777       if (need_operator)
1778           {
1779             size_t i;
1780             size_t len;
1781 
1782             success = 0;
1783 
1784             len = strlen (*mangled);
1785 
1786             for (i = 0; i < ARRAY_SIZE (optable); ++i)
1787               {
1788                 size_t l = strlen (optable[i].in);
1789 
1790                 if (l <= len
1791                       && memcmp (optable[i].in, *mangled, l) == 0)
1792                     {
1793                       string_appendn (s, " ", 1);
1794                       string_append (s, optable[i].out);
1795                       string_appendn (s, " ", 1);
1796                       success = 1;
1797                       (*mangled) += l;
1798                       break;
1799                     }
1800               }
1801 
1802             if (!success)
1803               break;
1804           }
1805       else
1806           need_operator = 1;
1807 
1808       success = demangle_template_value_parm (work, mangled, s, tk);
1809     }
1810 
1811   if (**mangled != 'W')
1812     success = 0;
1813   else
1814     {
1815       string_appendn (s, ")", 1);
1816       (*mangled)++;
1817     }
1818 
1819   return success;
1820 }
1821 
1822 static int
demangle_integral_value(struct work_stuff * work,const char ** mangled,string * s)1823 demangle_integral_value (struct work_stuff *work,
1824                          const char **mangled, string *s)
1825 {
1826   int success;
1827 
1828   if (**mangled == 'E')
1829     success = demangle_expression (work, mangled, s, tk_integral);
1830   else if (**mangled == 'Q' || **mangled == 'K')
1831     success = demangle_qualified (work, mangled, s, 0, 1);
1832   else
1833     {
1834       int value;
1835 
1836       /* By default, we let the number decide whether we shall consume an
1837            underscore.  */
1838       int multidigit_without_leading_underscore = 0;
1839       int leave_following_underscore = 0;
1840 
1841       success = 0;
1842 
1843       if (**mangled == '_')
1844         {
1845             if (mangled[0][1] == 'm')
1846               {
1847                 /* Since consume_count_with_underscores does not handle the
1848                      `m'-prefix we must do it here, using consume_count and
1849                      adjusting underscores: we have to consume the underscore
1850                      matching the prepended one.  */
1851                 multidigit_without_leading_underscore = 1;
1852                 string_appendn (s, "-", 1);
1853                 (*mangled) += 2;
1854               }
1855             else
1856               {
1857                 /* Do not consume a following underscore;
1858                    consume_count_with_underscores will consume what
1859                    should be consumed.  */
1860                 leave_following_underscore = 1;
1861               }
1862           }
1863       else
1864           {
1865             /* Negative numbers are indicated with a leading `m'.  */
1866             if (**mangled == 'm')
1867             {
1868               string_appendn (s, "-", 1);
1869               (*mangled)++;
1870             }
1871             /* Since consume_count_with_underscores does not handle
1872                multi-digit numbers that do not start with an underscore,
1873                and this number can be an integer template parameter,
1874                we have to call consume_count. */
1875             multidigit_without_leading_underscore = 1;
1876             /* These multi-digit numbers never end on an underscore,
1877                so if there is one then don't eat it. */
1878             leave_following_underscore = 1;
1879           }
1880 
1881       /* We must call consume_count if we expect to remove a trailing
1882            underscore, since consume_count_with_underscores expects
1883            the leading underscore (that we consumed) if it is to handle
1884            multi-digit numbers.  */
1885       if (multidigit_without_leading_underscore)
1886           value = consume_count (mangled);
1887       else
1888           value = consume_count_with_underscores (mangled);
1889 
1890       if (value != -1)
1891           {
1892             char buf[INTBUF_SIZE];
1893             sprintf (buf, "%d", value);
1894             string_append (s, buf);
1895 
1896             /* Numbers not otherwise delimited, might have an underscore
1897                appended as a delimeter, which we should skip.
1898 
1899                ??? This used to always remove a following underscore, which
1900                is wrong.  If other (arbitrary) cases are followed by an
1901                underscore, we need to do something more radical.  */
1902 
1903             if ((value > 9 || multidigit_without_leading_underscore)
1904                 && ! leave_following_underscore
1905                 && **mangled == '_')
1906               (*mangled)++;
1907 
1908             /* All is well.  */
1909             success = 1;
1910           }
1911       }
1912 
1913   return success;
1914 }
1915 
1916 /* Demangle the real value in MANGLED.  */
1917 
1918 static int
demangle_real_value(struct work_stuff * work,const char ** mangled,string * s)1919 demangle_real_value (struct work_stuff *work,
1920                      const char **mangled, string *s)
1921 {
1922   if (**mangled == 'E')
1923     return demangle_expression (work, mangled, s, tk_real);
1924 
1925   if (**mangled == 'm')
1926     {
1927       string_appendn (s, "-", 1);
1928       (*mangled)++;
1929     }
1930   while (ISDIGIT ((unsigned char)**mangled))
1931     {
1932       string_appendn (s, *mangled, 1);
1933       (*mangled)++;
1934     }
1935   if (**mangled == '.') /* fraction */
1936     {
1937       string_appendn (s, ".", 1);
1938       (*mangled)++;
1939       while (ISDIGIT ((unsigned char)**mangled))
1940           {
1941             string_appendn (s, *mangled, 1);
1942             (*mangled)++;
1943           }
1944     }
1945   if (**mangled == 'e') /* exponent */
1946     {
1947       string_appendn (s, "e", 1);
1948       (*mangled)++;
1949       while (ISDIGIT ((unsigned char)**mangled))
1950           {
1951             string_appendn (s, *mangled, 1);
1952             (*mangled)++;
1953           }
1954     }
1955 
1956   return 1;
1957 }
1958 
1959 static int
demangle_template_value_parm(struct work_stuff * work,const char ** mangled,string * s,type_kind_t tk)1960 demangle_template_value_parm (struct work_stuff *work, const char **mangled,
1961                               string *s, type_kind_t tk)
1962 {
1963   int success = 1;
1964 
1965   if (**mangled == 'Y')
1966     {
1967       /* The next argument is a template parameter. */
1968       int idx;
1969 
1970       (*mangled)++;
1971       idx = consume_count_with_underscores (mangled);
1972       if (idx == -1
1973             || (work->tmpl_argvec && idx >= work->ntmpl_args)
1974             || consume_count_with_underscores (mangled) == -1)
1975           return -1;
1976       if (work->tmpl_argvec)
1977           string_append (s, work->tmpl_argvec[idx]);
1978       else
1979           string_append_template_idx (s, idx);
1980     }
1981   else if (tk == tk_integral)
1982     success = demangle_integral_value (work, mangled, s);
1983   else if (tk == tk_char)
1984     {
1985       char tmp[2];
1986       int val;
1987       if (**mangled == 'm')
1988           {
1989             string_appendn (s, "-", 1);
1990             (*mangled)++;
1991           }
1992       string_appendn (s, "'", 1);
1993       val = consume_count(mangled);
1994       if (val <= 0)
1995           success = 0;
1996       else
1997           {
1998             tmp[0] = (char)val;
1999             tmp[1] = '\0';
2000             string_appendn (s, &tmp[0], 1);
2001             string_appendn (s, "'", 1);
2002           }
2003     }
2004   else if (tk == tk_bool)
2005     {
2006       int val = consume_count (mangled);
2007       if (val == 0)
2008           string_appendn (s, "false", 5);
2009       else if (val == 1)
2010           string_appendn (s, "true", 4);
2011       else
2012           success = 0;
2013     }
2014   else if (tk == tk_real)
2015     success = demangle_real_value (work, mangled, s);
2016   else if (tk == tk_pointer || tk == tk_reference)
2017     {
2018       if (**mangled == 'Q')
2019           success = demangle_qualified (work, mangled, s,
2020                                               /*isfuncname=*/0,
2021                                               /*append=*/1);
2022       else
2023           {
2024             int symbol_len  = consume_count (mangled);
2025             if (symbol_len == -1)
2026               return -1;
2027             if (symbol_len == 0)
2028               string_appendn (s, "0", 1);
2029             else
2030               {
2031                 char *p = XNEWVEC (char, symbol_len + 1), *q;
2032                 strncpy (p, *mangled, symbol_len);
2033                 p [symbol_len] = '\0';
2034                 /* We use cplus_demangle here, rather than
2035                      internal_cplus_demangle, because the name of the entity
2036                      mangled here does not make use of any of the squangling
2037                      or type-code information we have built up thus far; it is
2038                      mangled independently.  */
2039                 q = cplus_demangle (p, work->options);
2040                 if (tk == tk_pointer)
2041                     string_appendn (s, "&", 1);
2042                 /* FIXME: Pointer-to-member constants should get a
2043                      qualifying class name here.  */
2044                 if (q)
2045                     {
2046                       string_append (s, q);
2047                       free (q);
2048                     }
2049                 else
2050                     string_append (s, p);
2051                 free (p);
2052               }
2053             *mangled += symbol_len;
2054           }
2055     }
2056 
2057   return success;
2058 }
2059 
2060 /* Demangle the template name in MANGLED.  The full name of the
2061    template (e.g., S<int>) is placed in TNAME.  The name without the
2062    template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is
2063    non-NULL.  If IS_TYPE is nonzero, this template is a type template,
2064    not a function template.  If both IS_TYPE and REMEMBER are nonzero,
2065    the template is remembered in the list of back-referenceable
2066    types.  */
2067 
2068 static int
demangle_template(struct work_stuff * work,const char ** mangled,string * tname,string * trawname,int is_type,int remember)2069 demangle_template (struct work_stuff *work, const char **mangled,
2070                    string *tname, string *trawname,
2071                    int is_type, int remember)
2072 {
2073   int i;
2074   int r;
2075   int need_comma = 0;
2076   int success = 0;
2077   int is_java_array = 0;
2078   string temp;
2079 
2080   (*mangled)++;
2081   if (is_type)
2082     {
2083       /* get template name */
2084       if (**mangled == 'z')
2085           {
2086             int idx;
2087             (*mangled)++;
2088             (*mangled)++;
2089 
2090             idx = consume_count_with_underscores (mangled);
2091             if (idx == -1
2092                 || (work->tmpl_argvec && idx >= work->ntmpl_args)
2093                 || consume_count_with_underscores (mangled) == -1)
2094               return (0);
2095 
2096             if (work->tmpl_argvec)
2097               {
2098                 string_append (tname, work->tmpl_argvec[idx]);
2099                 if (trawname)
2100                     string_append (trawname, work->tmpl_argvec[idx]);
2101               }
2102             else
2103               {
2104                 string_append_template_idx (tname, idx);
2105                 if (trawname)
2106                     string_append_template_idx (trawname, idx);
2107               }
2108           }
2109       else
2110           {
2111             if ((r = consume_count (mangled)) <= 0
2112                 || (int) strlen (*mangled) < r)
2113               {
2114                 return (0);
2115               }
2116             is_java_array = (work -> options & DMGL_JAVA)
2117               && strncmp (*mangled, "JArray1Z", 8) == 0;
2118             if (! is_java_array)
2119               {
2120                 string_appendn (tname, *mangled, r);
2121               }
2122             if (trawname)
2123               string_appendn (trawname, *mangled, r);
2124             *mangled += r;
2125           }
2126     }
2127   if (!is_java_array)
2128     string_append (tname, "<");
2129   /* get size of template parameter list */
2130   if (!get_count (mangled, &r))
2131     {
2132       return (0);
2133     }
2134   if (!is_type)
2135     {
2136       /* Create an array for saving the template argument values. */
2137       work->tmpl_argvec = XNEWVEC (char *, r);
2138       work->ntmpl_args = r;
2139       for (i = 0; i < r; i++)
2140           work->tmpl_argvec[i] = 0;
2141     }
2142   for (i = 0; i < r; i++)
2143     {
2144       if (need_comma)
2145           {
2146             string_append (tname, ", ");
2147           }
2148       /* Z for type parameters */
2149       if (**mangled == 'Z')
2150           {
2151             (*mangled)++;
2152             /* temp is initialized in do_type */
2153             success = do_type (work, mangled, &temp);
2154             if (success)
2155               {
2156                 string_appends (tname, &temp);
2157 
2158                 if (!is_type)
2159                     {
2160                       /* Save the template argument. */
2161                       int len = temp.p - temp.b;
2162                       work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
2163                       memcpy (work->tmpl_argvec[i], temp.b, len);
2164                       work->tmpl_argvec[i][len] = '\0';
2165                     }
2166               }
2167             string_delete(&temp);
2168             if (!success)
2169               {
2170                 break;
2171               }
2172           }
2173       /* z for template parameters */
2174       else if (**mangled == 'z')
2175           {
2176             int r2;
2177             (*mangled)++;
2178             success = demangle_template_template_parm (work, mangled, tname);
2179 
2180             if (success
2181                 && (r2 = consume_count (mangled)) > 0
2182                 && (int) strlen (*mangled) >= r2)
2183               {
2184                 string_append (tname, " ");
2185                 string_appendn (tname, *mangled, r2);
2186                 if (!is_type)
2187                     {
2188                       /* Save the template argument. */
2189                       int len = r2;
2190                       work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
2191                       memcpy (work->tmpl_argvec[i], *mangled, len);
2192                       work->tmpl_argvec[i][len] = '\0';
2193                     }
2194                 *mangled += r2;
2195               }
2196             if (!success)
2197               {
2198                 break;
2199               }
2200           }
2201       else
2202           {
2203             string  param;
2204             string* s;
2205 
2206             /* otherwise, value parameter */
2207 
2208             /* temp is initialized in do_type */
2209             success = do_type (work, mangled, &temp);
2210             string_delete(&temp);
2211             if (!success)
2212               break;
2213 
2214             if (!is_type)
2215               {
2216                 s = &param;
2217                 string_init (s);
2218               }
2219             else
2220               s = tname;
2221 
2222             success = demangle_template_value_parm (work, mangled, s,
2223                                                               (type_kind_t) success);
2224 
2225             if (!success)
2226               {
2227                 if (!is_type)
2228                     string_delete (s);
2229                 success = 0;
2230                 break;
2231               }
2232 
2233             if (!is_type)
2234               {
2235                 int len = s->p - s->b;
2236                 work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
2237                 memcpy (work->tmpl_argvec[i], s->b, len);
2238                 work->tmpl_argvec[i][len] = '\0';
2239 
2240                 string_appends (tname, s);
2241                 string_delete (s);
2242               }
2243           }
2244       need_comma = 1;
2245     }
2246   if (is_java_array)
2247     {
2248       string_append (tname, "[]");
2249     }
2250   else
2251     {
2252       if (tname->p[-1] == '>')
2253           string_append (tname, " ");
2254       string_append (tname, ">");
2255     }
2256 
2257   if (is_type && remember)
2258     {
2259       const int bindex = register_Btype (work);
2260       remember_Btype (work, tname->b, LEN_STRING (tname), bindex);
2261     }
2262 
2263   /*
2264     if (work -> static_type)
2265     {
2266     string_append (declp, *mangled + 1);
2267     *mangled += strlen (*mangled);
2268     success = 1;
2269     }
2270     else
2271     {
2272     success = demangle_args (work, mangled, declp);
2273     }
2274     }
2275     */
2276   return (success);
2277 }
2278 
2279 static int
arm_pt(struct work_stuff * work,const char * mangled,int n,const char ** anchor,const char ** args)2280 arm_pt (struct work_stuff *work, const char *mangled,
2281         int n, const char **anchor, const char **args)
2282 {
2283   /* Check if ARM template with "__pt__" in it ("parameterized type") */
2284   /* Allow HP also here, because HP's cfront compiler follows ARM to some extent */
2285   if ((ARM_DEMANGLING || HP_DEMANGLING) && (*anchor = strstr (mangled, "__pt__")))
2286     {
2287       int len;
2288       *args = *anchor + 6;
2289       len = consume_count (args);
2290       if (len == -1)
2291           return 0;
2292       if (*args + len == mangled + n && **args == '_')
2293           {
2294             ++*args;
2295             return 1;
2296           }
2297     }
2298   if (AUTO_DEMANGLING || EDG_DEMANGLING)
2299     {
2300       if ((*anchor = strstr (mangled, "__tm__"))
2301           || (*anchor = strstr (mangled, "__ps__"))
2302           || (*anchor = strstr (mangled, "__pt__")))
2303         {
2304           int len;
2305           *args = *anchor + 6;
2306           len = consume_count (args);
2307             if (len == -1)
2308               return 0;
2309           if (*args + len == mangled + n && **args == '_')
2310             {
2311               ++*args;
2312               return 1;
2313             }
2314         }
2315       else if ((*anchor = strstr (mangled, "__S")))
2316         {
2317             int len;
2318             *args = *anchor + 3;
2319             len = consume_count (args);
2320             if (len == -1)
2321               return 0;
2322             if (*args + len == mangled + n && **args == '_')
2323             {
2324               ++*args;
2325                 return 1;
2326             }
2327         }
2328     }
2329 
2330   return 0;
2331 }
2332 
2333 static void
demangle_arm_hp_template(struct work_stuff * work,const char ** mangled,int n,string * declp)2334 demangle_arm_hp_template (struct work_stuff *work, const char **mangled,
2335                           int n, string *declp)
2336 {
2337   const char *p;
2338   const char *args;
2339   const char *e = *mangled + n;
2340   string arg;
2341 
2342   /* Check for HP aCC template spec: classXt1t2 where t1, t2 are
2343      template args */
2344   if (HP_DEMANGLING && ((*mangled)[n] == 'X'))
2345     {
2346       char *start_spec_args = NULL;
2347       int hold_options;
2348 
2349       /* First check for and omit template specialization pseudo-arguments,
2350          such as in "Spec<#1,#1.*>" */
2351       start_spec_args = strchr (*mangled, '<');
2352       if (start_spec_args && (start_spec_args - *mangled < n))
2353         string_appendn (declp, *mangled, start_spec_args - *mangled);
2354       else
2355         string_appendn (declp, *mangled, n);
2356       (*mangled) += n + 1;
2357       string_init (&arg);
2358       if (work->temp_start == -1) /* non-recursive call */
2359         work->temp_start = declp->p - declp->b;
2360 
2361       /* We want to unconditionally demangle parameter types in
2362            template parameters.  */
2363       hold_options = work->options;
2364       work->options |= DMGL_PARAMS;
2365 
2366       string_append (declp, "<");
2367       while (1)
2368         {
2369           string_delete (&arg);
2370           switch (**mangled)
2371             {
2372               case 'T':
2373                 /* 'T' signals a type parameter */
2374                 (*mangled)++;
2375                 if (!do_type (work, mangled, &arg))
2376                   goto hpacc_template_args_done;
2377                 break;
2378 
2379               case 'U':
2380               case 'S':
2381                 /* 'U' or 'S' signals an integral value */
2382                 if (!do_hpacc_template_const_value (work, mangled, &arg))
2383                   goto hpacc_template_args_done;
2384                 break;
2385 
2386               case 'A':
2387                 /* 'A' signals a named constant expression (literal) */
2388                 if (!do_hpacc_template_literal (work, mangled, &arg))
2389                   goto hpacc_template_args_done;
2390                 break;
2391 
2392               default:
2393                 /* Today, 1997-09-03, we have only the above types
2394                    of template parameters */
2395                 /* FIXME: maybe this should fail and return null */
2396                 goto hpacc_template_args_done;
2397             }
2398           string_appends (declp, &arg);
2399          /* Check if we're at the end of template args.
2400              0 if at end of static member of template class,
2401              _ if done with template args for a function */
2402           if ((**mangled == '\000') || (**mangled == '_'))
2403             break;
2404           else
2405             string_append (declp, ",");
2406         }
2407     hpacc_template_args_done:
2408       string_append (declp, ">");
2409       string_delete (&arg);
2410       if (**mangled == '_')
2411         (*mangled)++;
2412       work->options = hold_options;
2413       return;
2414     }
2415   /* ARM template? (Also handles HP cfront extensions) */
2416   else if (arm_pt (work, *mangled, n, &p, &args))
2417     {
2418       int hold_options;
2419       string type_str;
2420 
2421       string_init (&arg);
2422       string_appendn (declp, *mangled, p - *mangled);
2423       if (work->temp_start == -1)  /* non-recursive call */
2424           work->temp_start = declp->p - declp->b;
2425 
2426       /* We want to unconditionally demangle parameter types in
2427            template parameters.  */
2428       hold_options = work->options;
2429       work->options |= DMGL_PARAMS;
2430 
2431       string_append (declp, "<");
2432       /* should do error checking here */
2433       while (args < e) {
2434           string_delete (&arg);
2435 
2436           /* Check for type or literal here */
2437           switch (*args)
2438             {
2439               /* HP cfront extensions to ARM for template args */
2440               /* spec: Xt1Lv1 where t1 is a type, v1 is a literal value */
2441               /* FIXME: We handle only numeric literals for HP cfront */
2442           case 'X':
2443             /* A typed constant value follows */
2444             args++;
2445             if (!do_type (work, &args, &type_str))
2446                 goto cfront_template_args_done;
2447             string_append (&arg, "(");
2448             string_appends (&arg, &type_str);
2449             string_delete (&type_str);
2450             string_append (&arg, ")");
2451             if (*args != 'L')
2452               goto cfront_template_args_done;
2453             args++;
2454             /* Now snarf a literal value following 'L' */
2455             if (!snarf_numeric_literal (&args, &arg))
2456                 goto cfront_template_args_done;
2457             break;
2458 
2459           case 'L':
2460             /* Snarf a literal following 'L' */
2461             args++;
2462             if (!snarf_numeric_literal (&args, &arg))
2463                 goto cfront_template_args_done;
2464             break;
2465           default:
2466             /* Not handling other HP cfront stuff */
2467             {
2468               const char* old_args = args;
2469               if (!do_type (work, &args, &arg))
2470                 goto cfront_template_args_done;
2471 
2472               /* Fail if we didn't make any progress: prevent infinite loop. */
2473               if (args == old_args)
2474                     {
2475                       work->options = hold_options;
2476                       return;
2477                     }
2478             }
2479             }
2480           string_appends (declp, &arg);
2481           string_append (declp, ",");
2482       }
2483     cfront_template_args_done:
2484       string_delete (&arg);
2485       if (args >= e)
2486           --declp->p; /* remove extra comma */
2487       string_append (declp, ">");
2488       work->options = hold_options;
2489     }
2490   else if (n>10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
2491              && (*mangled)[9] == 'N'
2492              && (*mangled)[8] == (*mangled)[10]
2493              && strchr (cplus_markers, (*mangled)[8]))
2494     {
2495       /* A member of the anonymous namespace.  */
2496       string_append (declp, "{anonymous}");
2497     }
2498   else
2499     {
2500       if (work->temp_start == -1) /* non-recursive call only */
2501           work->temp_start = 0;     /* disable in recursive calls */
2502       string_appendn (declp, *mangled, n);
2503     }
2504   *mangled += n;
2505 }
2506 
2507 /* Extract a class name, possibly a template with arguments, from the
2508    mangled string; qualifiers, local class indicators, etc. have
2509    already been dealt with */
2510 
2511 static int
demangle_class_name(struct work_stuff * work,const char ** mangled,string * declp)2512 demangle_class_name (struct work_stuff *work, const char **mangled,
2513                      string *declp)
2514 {
2515   int n;
2516   int success = 0;
2517 
2518   n = consume_count (mangled);
2519   if (n == -1)
2520     return 0;
2521   if ((int) strlen (*mangled) >= n)
2522     {
2523       demangle_arm_hp_template (work, mangled, n, declp);
2524       success = 1;
2525     }
2526 
2527   return (success);
2528 }
2529 
2530 /*
2531 
2532 LOCAL FUNCTION
2533 
2534           demangle_class -- demangle a mangled class sequence
2535 
2536 SYNOPSIS
2537 
2538           static int
2539           demangle_class (struct work_stuff *work, const char **mangled,
2540                               strint *declp)
2541 
2542 DESCRIPTION
2543 
2544           DECLP points to the buffer into which demangling is being done.
2545 
2546           *MANGLED points to the current token to be demangled.  On input,
2547           it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
2548           On exit, it points to the next token after the mangled class on
2549           success, or the first unconsumed token on failure.
2550 
2551           If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
2552           we are demangling a constructor or destructor.  In this case
2553           we prepend "class::class" or "class::~class" to DECLP.
2554 
2555           Otherwise, we prepend "class::" to the current DECLP.
2556 
2557           Reset the constructor/destructor flags once they have been
2558           "consumed".  This allows demangle_class to be called later during
2559           the same demangling, to do normal class demangling.
2560 
2561           Returns 1 if demangling is successful, 0 otherwise.
2562 
2563 */
2564 
2565 static int
demangle_class(struct work_stuff * work,const char ** mangled,string * declp)2566 demangle_class (struct work_stuff *work, const char **mangled, string *declp)
2567 {
2568   int success = 0;
2569   int btype;
2570   string class_name;
2571   char *save_class_name_end = 0;
2572 
2573   string_init (&class_name);
2574   btype = register_Btype (work);
2575   if (demangle_class_name (work, mangled, &class_name))
2576     {
2577       save_class_name_end = class_name.p;
2578       if ((work->constructor & 1) || (work->destructor & 1))
2579           {
2580           /* adjust so we don't include template args */
2581           if (work->temp_start && (work->temp_start != -1))
2582             {
2583               class_name.p = class_name.b + work->temp_start;
2584             }
2585             string_prepends (declp, &class_name);
2586             if (work -> destructor & 1)
2587               {
2588                 string_prepend (declp, "~");
2589               work -> destructor -= 1;
2590               }
2591             else
2592               {
2593                 work -> constructor -= 1;
2594               }
2595           }
2596       class_name.p = save_class_name_end;
2597       remember_Ktype (work, class_name.b, LEN_STRING(&class_name));
2598       remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype);
2599       string_prepend (declp, SCOPE_STRING (work));
2600       string_prepends (declp, &class_name);
2601       success = 1;
2602     }
2603   string_delete (&class_name);
2604   return (success);
2605 }
2606 
2607 
2608 /* Called when there's a "__" in the mangled name, with `scan' pointing to
2609    the rightmost guess.
2610 
2611    Find the correct "__"-sequence where the function name ends and the
2612    signature starts, which is ambiguous with GNU mangling.
2613    Call demangle_signature here, so we can make sure we found the right
2614    one; *mangled will be consumed so caller will not make further calls to
2615    demangle_signature.  */
2616 
2617 static int
iterate_demangle_function(struct work_stuff * work,const char ** mangled,string * declp,const char * scan)2618 iterate_demangle_function (struct work_stuff *work, const char **mangled,
2619                            string *declp, const char *scan)
2620 {
2621   const char *mangle_init = *mangled;
2622   int success = 0;
2623   string decl_init;
2624   struct work_stuff work_init;
2625 
2626   if (*(scan + 2) == '\0')
2627     return 0;
2628 
2629   /* Do not iterate for some demangling modes, or if there's only one
2630      "__"-sequence.  This is the normal case.  */
2631   if (ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING
2632       || strstr (scan + 2, "__") == NULL)
2633     return demangle_function_name (work, mangled, declp, scan);
2634 
2635   /* Save state so we can restart if the guess at the correct "__" was
2636      wrong.  */
2637   string_init (&decl_init);
2638   string_appends (&decl_init, declp);
2639   memset (&work_init, 0, sizeof work_init);
2640   work_stuff_copy_to_from (&work_init, work);
2641 
2642   /* Iterate over occurrences of __, allowing names and types to have a
2643      "__" sequence in them.  We must start with the first (not the last)
2644      occurrence, since "__" most often occur between independent mangled
2645      parts, hence starting at the last occurence inside a signature
2646      might get us a "successful" demangling of the signature.  */
2647 
2648   while (scan[2])
2649     {
2650       if (demangle_function_name (work, mangled, declp, scan))
2651           {
2652             success = demangle_signature (work, mangled, declp);
2653             if (success)
2654               break;
2655           }
2656 
2657       /* Reset demangle state for the next round.  */
2658       *mangled = mangle_init;
2659       string_clear (declp);
2660       string_appends (declp, &decl_init);
2661       work_stuff_copy_to_from (work, &work_init);
2662 
2663       /* Leave this underscore-sequence.  */
2664       scan += 2;
2665 
2666       /* Scan for the next "__" sequence.  */
2667       while (*scan && (scan[0] != '_' || scan[1] != '_'))
2668           scan++;
2669 
2670       /* Move to last "__" in this sequence.  */
2671       while (*scan && *scan == '_')
2672           scan++;
2673       scan -= 2;
2674     }
2675 
2676   /* Delete saved state.  */
2677   delete_work_stuff (&work_init);
2678   string_delete (&decl_init);
2679 
2680   return success;
2681 }
2682 
2683 /*
2684 
2685 LOCAL FUNCTION
2686 
2687           demangle_prefix -- consume the mangled name prefix and find signature
2688 
2689 SYNOPSIS
2690 
2691           static int
2692           demangle_prefix (struct work_stuff *work, const char **mangled,
2693                                string *declp);
2694 
2695 DESCRIPTION
2696 
2697           Consume and demangle the prefix of the mangled name.
2698           While processing the function name root, arrange to call
2699           demangle_signature if the root is ambiguous.
2700 
2701           DECLP points to the string buffer into which demangled output is
2702           placed.  On entry, the buffer is empty.  On exit it contains
2703           the root function name, the demangled operator name, or in some
2704           special cases either nothing or the completely demangled result.
2705 
2706           MANGLED points to the current pointer into the mangled name.  As each
2707           token of the mangled name is consumed, it is updated.  Upon entry
2708           the current mangled name pointer points to the first character of
2709           the mangled name.  Upon exit, it should point to the first character
2710           of the signature if demangling was successful, or to the first
2711           unconsumed character if demangling of the prefix was unsuccessful.
2712 
2713           Returns 1 on success, 0 otherwise.
2714  */
2715 
2716 static int
demangle_prefix(struct work_stuff * work,const char ** mangled,string * declp)2717 demangle_prefix (struct work_stuff *work, const char **mangled,
2718                  string *declp)
2719 {
2720   int success = 1;
2721   const char *scan;
2722   int i;
2723 
2724   if (strlen(*mangled) > 6
2725       && (strncmp(*mangled, "_imp__", 6) == 0
2726           || strncmp(*mangled, "__imp_", 6) == 0))
2727     {
2728       /* it's a symbol imported from a PE dynamic library. Check for both
2729          new style prefix _imp__ and legacy __imp_ used by older versions
2730            of dlltool. */
2731       (*mangled) += 6;
2732       work->dllimported = 1;
2733     }
2734   else if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
2735     {
2736       char *marker = strchr (cplus_markers, (*mangled)[8]);
2737       if (marker != NULL && *marker == (*mangled)[10])
2738           {
2739             if ((*mangled)[9] == 'D')
2740               {
2741                 /* it's a GNU global destructor to be executed at program exit */
2742                 (*mangled) += 11;
2743                 work->destructor = 2;
2744                 if (gnu_special (work, mangled, declp))
2745                     return success;
2746               }
2747             else if ((*mangled)[9] == 'I')
2748               {
2749                 /* it's a GNU global constructor to be executed at program init */
2750                 (*mangled) += 11;
2751                 work->constructor = 2;
2752                 if (gnu_special (work, mangled, declp))
2753                     return success;
2754               }
2755           }
2756     }
2757   else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__std__", 7) == 0)
2758     {
2759       /* it's a ARM global destructor to be executed at program exit */
2760       (*mangled) += 7;
2761       work->destructor = 2;
2762     }
2763   else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__sti__", 7) == 0)
2764     {
2765       /* it's a ARM global constructor to be executed at program initial */
2766       (*mangled) += 7;
2767       work->constructor = 2;
2768     }
2769 
2770   /*  This block of code is a reduction in strength time optimization
2771       of:
2772       scan = strstr (*mangled, "__"); */
2773 
2774   {
2775     scan = *mangled;
2776 
2777     do {
2778       scan = strchr (scan, '_');
2779     } while (scan != NULL && *++scan != '_');
2780 
2781     if (scan != NULL) --scan;
2782   }
2783 
2784   if (scan != NULL)
2785     {
2786       /* We found a sequence of two or more '_', ensure that we start at
2787            the last pair in the sequence.  */
2788       i = strspn (scan, "_");
2789       if (i > 2)
2790           {
2791             scan += (i - 2);
2792           }
2793     }
2794 
2795   if (scan == NULL)
2796     {
2797       success = 0;
2798     }
2799   else if (work -> static_type)
2800     {
2801       if (!ISDIGIT ((unsigned char)scan[0]) && (scan[0] != 't'))
2802           {
2803             success = 0;
2804           }
2805     }
2806   else if ((scan == *mangled)
2807              && (ISDIGIT ((unsigned char)scan[2]) || (scan[2] == 'Q')
2808                  || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H')))
2809     {
2810       /* The ARM says nothing about the mangling of local variables.
2811            But cfront mangles local variables by prepending __<nesting_level>
2812            to them. As an extension to ARM demangling we handle this case.  */
2813       if ((LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING)
2814             && ISDIGIT ((unsigned char)scan[2]))
2815           {
2816             *mangled = scan + 2;
2817             consume_count (mangled);
2818             string_append (declp, *mangled);
2819             *mangled += strlen (*mangled);
2820             success = 1;
2821           }
2822       else
2823           {
2824             /* A GNU style constructor starts with __[0-9Qt].  But cfront uses
2825                names like __Q2_3foo3bar for nested type names.  So don't accept
2826                this style of constructor for cfront demangling.  A GNU
2827                style member-template constructor starts with 'H'. */
2828             if (!(LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING))
2829               work -> constructor += 1;
2830             *mangled = scan + 2;
2831           }
2832     }
2833   else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
2834     {
2835       /* Cfront-style parameterized type.  Handled later as a signature. */
2836       success = 1;
2837 
2838       /* ARM template? */
2839       demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
2840     }
2841   else if (EDG_DEMANGLING && ((scan[2] == 't' && scan[3] == 'm')
2842                               || (scan[2] == 'p' && scan[3] == 's')
2843                               || (scan[2] == 'p' && scan[3] == 't')))
2844     {
2845       /* EDG-style parameterized type.  Handled later as a signature. */
2846       success = 1;
2847 
2848       /* EDG template? */
2849       demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
2850     }
2851   else if ((scan == *mangled) && !ISDIGIT ((unsigned char)scan[2])
2852              && (scan[2] != 't'))
2853     {
2854       /* Mangled name starts with "__".  Skip over any leading '_' characters,
2855            then find the next "__" that separates the prefix from the signature.
2856            */
2857       if (!(ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
2858             || (arm_special (mangled, declp) == 0))
2859           {
2860             while (*scan == '_')
2861               {
2862                 scan++;
2863               }
2864             if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
2865               {
2866                 /* No separator (I.E. "__not_mangled"), or empty signature
2867                      (I.E. "__not_mangled_either__") */
2868                 success = 0;
2869               }
2870             else
2871               return iterate_demangle_function (work, mangled, declp, scan);
2872           }
2873     }
2874   else if (*(scan + 2) != '\0')
2875     {
2876       /* Mangled name does not start with "__" but does have one somewhere
2877            in there with non empty stuff after it.  Looks like a global
2878            function name.  Iterate over all "__":s until the right
2879            one is found.  */
2880       return iterate_demangle_function (work, mangled, declp, scan);
2881     }
2882   else
2883     {
2884       /* Doesn't look like a mangled name */
2885       success = 0;
2886     }
2887 
2888   if (!success && (work->constructor == 2 || work->destructor == 2))
2889     {
2890       string_append (declp, *mangled);
2891       *mangled += strlen (*mangled);
2892       success = 1;
2893     }
2894   return (success);
2895 }
2896 
2897 /*
2898 
2899 LOCAL FUNCTION
2900 
2901           gnu_special -- special handling of gnu mangled strings
2902 
2903 SYNOPSIS
2904 
2905           static int
2906           gnu_special (struct work_stuff *work, const char **mangled,
2907                          string *declp);
2908 
2909 
2910 DESCRIPTION
2911 
2912           Process some special GNU style mangling forms that don't fit
2913           the normal pattern.  For example:
2914 
2915                     _$_3foo             (destructor for class foo)
2916                     _vt$foo             (foo virtual table)
2917                     _vt$foo$bar         (foo::bar virtual table)
2918                     __vt_foo  (foo virtual table, new style with thunks)
2919                     _3foo$varname       (static data member)
2920                     _Q22rs2tu$vw        (static data member)
2921                     __t6vector1Zii      (constructor with template)
2922                     __thunk_4__$_7ostream (virtual function thunk)
2923  */
2924 
2925 static int
gnu_special(struct work_stuff * work,const char ** mangled,string * declp)2926 gnu_special (struct work_stuff *work, const char **mangled, string *declp)
2927 {
2928   int n;
2929   int success = 1;
2930   const char *p;
2931 
2932   if ((*mangled)[0] == '_'
2933       && strchr (cplus_markers, (*mangled)[1]) != NULL
2934       && (*mangled)[2] == '_')
2935     {
2936       /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
2937       (*mangled) += 3;
2938       work -> destructor += 1;
2939     }
2940   else if ((*mangled)[0] == '_'
2941              && (((*mangled)[1] == '_'
2942                     && (*mangled)[2] == 'v'
2943                     && (*mangled)[3] == 't'
2944                     && (*mangled)[4] == '_')
2945                  || ((*mangled)[1] == 'v'
2946                        && (*mangled)[2] == 't'
2947                        && strchr (cplus_markers, (*mangled)[3]) != NULL)))
2948     {
2949       /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
2950          and create the decl.  Note that we consume the entire mangled
2951            input string, which means that demangle_signature has no work
2952            to do.  */
2953       if ((*mangled)[2] == 'v')
2954           (*mangled) += 5; /* New style, with thunks: "__vt_" */
2955       else
2956           (*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
2957       while (**mangled != '\0')
2958           {
2959             switch (**mangled)
2960               {
2961               case 'Q':
2962               case 'K':
2963                 success = demangle_qualified (work, mangled, declp, 0, 1);
2964                 break;
2965               case 't':
2966                 success = demangle_template (work, mangled, declp, 0, 1,
2967                                                      1);
2968                 break;
2969               default:
2970                 if (ISDIGIT((unsigned char)*mangled[0]))
2971                     {
2972                       n = consume_count(mangled);
2973                       /* We may be seeing a too-large size, or else a
2974                          ".<digits>" indicating a static local symbol.  In
2975                          any case, declare victory and move on; *don't* try
2976                          to use n to allocate.  */
2977                       if (n > (int) strlen (*mangled))
2978                         {
2979                           success = 1;
2980                           break;
2981                         }
2982                     }
2983                 else
2984                     {
2985                       n = strcspn (*mangled, cplus_markers);
2986                     }
2987                 string_appendn (declp, *mangled, n);
2988                 (*mangled) += n;
2989               }
2990 
2991             p = strpbrk (*mangled, cplus_markers);
2992             if (success && ((p == NULL) || (p == *mangled)))
2993               {
2994                 if (p != NULL)
2995                     {
2996                       string_append (declp, SCOPE_STRING (work));
2997                       (*mangled)++;
2998                     }
2999               }
3000             else
3001               {
3002                 success = 0;
3003                 break;
3004               }
3005           }
3006       if (success)
3007           string_append (declp, " virtual table");
3008     }
3009   else if ((*mangled)[0] == '_'
3010              && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
3011              && (p = strpbrk (*mangled, cplus_markers)) != NULL)
3012     {
3013       /* static data member, "_3foo$varname" for example */
3014       (*mangled)++;
3015       switch (**mangled)
3016           {
3017           case 'Q':
3018           case 'K':
3019             success = demangle_qualified (work, mangled, declp, 0, 1);
3020             break;
3021           case 't':
3022             success = demangle_template (work, mangled, declp, 0, 1, 1);
3023             break;
3024           default:
3025             n = consume_count (mangled);
3026             if (n < 0 || n > (long) strlen (*mangled))
3027               {
3028                 success = 0;
3029                 break;
3030               }
3031 
3032             if (n > 10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
3033                 && (*mangled)[9] == 'N'
3034                 && (*mangled)[8] == (*mangled)[10]
3035                 && strchr (cplus_markers, (*mangled)[8]))
3036               {
3037                 /* A member of the anonymous namespace.  There's information
3038                      about what identifier or filename it was keyed to, but
3039                      it's just there to make the mangled name unique; we just
3040                      step over it.  */
3041                 string_append (declp, "{anonymous}");
3042                 (*mangled) += n;
3043 
3044                 /* Now p points to the marker before the N, so we need to
3045                      update it to the first marker after what we consumed.  */
3046                 p = strpbrk (*mangled, cplus_markers);
3047                 break;
3048               }
3049 
3050             string_appendn (declp, *mangled, n);
3051             (*mangled) += n;
3052           }
3053       if (success && (p == *mangled))
3054           {
3055             /* Consumed everything up to the cplus_marker, append the
3056                variable name.  */
3057             (*mangled)++;
3058             string_append (declp, SCOPE_STRING (work));
3059             n = strlen (*mangled);
3060             string_appendn (declp, *mangled, n);
3061             (*mangled) += n;
3062           }
3063       else
3064           {
3065             success = 0;
3066           }
3067     }
3068   else if (strncmp (*mangled, "__thunk_", 8) == 0)
3069     {
3070       int delta;
3071 
3072       (*mangled) += 8;
3073       delta = consume_count (mangled);
3074       if (delta == -1)
3075           success = 0;
3076       else
3077           {
3078             char *method = internal_cplus_demangle (work, ++*mangled);
3079 
3080             if (method)
3081               {
3082                 char buf[50];
3083                 sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
3084                 string_append (declp, buf);
3085                 string_append (declp, method);
3086                 free (method);
3087                 n = strlen (*mangled);
3088                 (*mangled) += n;
3089               }
3090             else
3091               {
3092                 success = 0;
3093               }
3094           }
3095     }
3096   else if (strncmp (*mangled, "__t", 3) == 0
3097              && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f'))
3098     {
3099       p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function";
3100       (*mangled) += 4;
3101       switch (**mangled)
3102           {
3103           case 'Q':
3104           case 'K':
3105             success = demangle_qualified (work, mangled, declp, 0, 1);
3106             break;
3107           case 't':
3108             success = demangle_template (work, mangled, declp, 0, 1, 1);
3109             break;
3110           default:
3111             success = do_type (work, mangled, declp);
3112             break;
3113           }
3114       if (success && **mangled != '\0')
3115           success = 0;
3116       if (success)
3117           string_append (declp, p);
3118     }
3119   else
3120     {
3121       success = 0;
3122     }
3123   return (success);
3124 }
3125 
3126 static void
recursively_demangle(struct work_stuff * work,const char ** mangled,string * result,int namelength)3127 recursively_demangle(struct work_stuff *work, const char **mangled,
3128                      string *result, int namelength)
3129 {
3130   char * recurse = (char *)NULL;
3131   char * recurse_dem = (char *)NULL;
3132 
3133   recurse = XNEWVEC (char, namelength + 1);
3134   memcpy (recurse, *mangled, namelength);
3135   recurse[namelength] = '\000';
3136 
3137   recurse_dem = cplus_demangle (recurse, work->options);
3138 
3139   if (recurse_dem)
3140     {
3141       string_append (result, recurse_dem);
3142       free (recurse_dem);
3143     }
3144   else
3145     {
3146       string_appendn (result, *mangled, namelength);
3147     }
3148   free (recurse);
3149   *mangled += namelength;
3150 }
3151 
3152 /*
3153 
3154 LOCAL FUNCTION
3155 
3156           arm_special -- special handling of ARM/lucid mangled strings
3157 
3158 SYNOPSIS
3159 
3160           static int
3161           arm_special (const char **mangled,
3162                          string *declp);
3163 
3164 
3165 DESCRIPTION
3166 
3167           Process some special ARM style mangling forms that don't fit
3168           the normal pattern.  For example:
3169 
3170                     __vtbl__3foo                  (foo virtual table)
3171                     __vtbl__3foo__3bar  (bar::foo virtual table)
3172 
3173  */
3174 
3175 static int
arm_special(const char ** mangled,string * declp)3176 arm_special (const char **mangled, string *declp)
3177 {
3178   int n;
3179   int success = 1;
3180   const char *scan;
3181 
3182   if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
3183     {
3184       /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
3185          and create the decl.  Note that we consume the entire mangled
3186            input string, which means that demangle_signature has no work
3187            to do.  */
3188       scan = *mangled + ARM_VTABLE_STRLEN;
3189       while (*scan != '\0')        /* first check it can be demangled */
3190         {
3191           n = consume_count (&scan);
3192           if (n == -1)
3193               {
3194                 return (0);           /* no good */
3195               }
3196           scan += n;
3197           if (scan[0] == '_' && scan[1] == '_')
3198               {
3199                 scan += 2;
3200               }
3201         }
3202       (*mangled) += ARM_VTABLE_STRLEN;
3203       while (**mangled != '\0')
3204           {
3205             n = consume_count (mangled);
3206           if (n == -1
3207                 || n > (long) strlen (*mangled))
3208               return 0;
3209             string_prependn (declp, *mangled, n);
3210             (*mangled) += n;
3211             if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
3212               {
3213                 string_prepend (declp, "::");
3214                 (*mangled) += 2;
3215               }
3216           }
3217       string_append (declp, " virtual table");
3218     }
3219   else
3220     {
3221       success = 0;
3222     }
3223   return (success);
3224 }
3225 
3226 /*
3227 
3228 LOCAL FUNCTION
3229 
3230           demangle_qualified -- demangle 'Q' qualified name strings
3231 
3232 SYNOPSIS
3233 
3234           static int
3235           demangle_qualified (struct work_stuff *, const char *mangled,
3236                                   string *result, int isfuncname, int append);
3237 
3238 DESCRIPTION
3239 
3240           Demangle a qualified name, such as "Q25Outer5Inner" which is
3241           the mangled form of "Outer::Inner".  The demangled output is
3242           prepended or appended to the result string according to the
3243           state of the append flag.
3244 
3245           If isfuncname is nonzero, then the qualified name we are building
3246           is going to be used as a member function name, so if it is a
3247           constructor or destructor function, append an appropriate
3248           constructor or destructor name.  I.E. for the above example,
3249           the result for use as a constructor is "Outer::Inner::Inner"
3250           and the result for use as a destructor is "Outer::Inner::~Inner".
3251 
3252 BUGS
3253 
3254           Numeric conversion is ASCII dependent (FIXME).
3255 
3256  */
3257 
3258 static int
demangle_qualified(struct work_stuff * work,const char ** mangled,string * result,int isfuncname,int append)3259 demangle_qualified (struct work_stuff *work, const char **mangled,
3260                     string *result, int isfuncname, int append)
3261 {
3262   int qualifiers = 0;
3263   int success = 1;
3264   char num[2];
3265   string temp;
3266   string last_name;
3267   int bindex = register_Btype (work);
3268 
3269   /* We only make use of ISFUNCNAME if the entity is a constructor or
3270      destructor.  */
3271   isfuncname = (isfuncname
3272                     && ((work->constructor & 1) || (work->destructor & 1)));
3273 
3274   string_init (&temp);
3275   string_init (&last_name);
3276 
3277   if ((*mangled)[0] == 'K')
3278     {
3279     /* Squangling qualified name reuse */
3280       int idx;
3281       (*mangled)++;
3282       idx = consume_count_with_underscores (mangled);
3283       if (idx == -1 || idx >= work -> numk)
3284         success = 0;
3285       else
3286         string_append (&temp, work -> ktypevec[idx]);
3287     }
3288   else
3289     switch ((*mangled)[1])
3290     {
3291     case '_':
3292       /* GNU mangled name with more than 9 classes.  The count is preceded
3293            by an underscore (to distinguish it from the <= 9 case) and followed
3294            by an underscore.  */
3295       (*mangled)++;
3296       qualifiers = consume_count_with_underscores (mangled);
3297       if (qualifiers == -1)
3298           success = 0;
3299       break;
3300 
3301     case '1':
3302     case '2':
3303     case '3':
3304     case '4':
3305     case '5':
3306     case '6':
3307     case '7':
3308     case '8':
3309     case '9':
3310       /* The count is in a single digit.  */
3311       num[0] = (*mangled)[1];
3312       num[1] = '\0';
3313       qualifiers = atoi (num);
3314 
3315       /* If there is an underscore after the digit, skip it.  This is
3316            said to be for ARM-qualified names, but the ARM makes no
3317            mention of such an underscore.  Perhaps cfront uses one.  */
3318       if ((*mangled)[2] == '_')
3319           {
3320             (*mangled)++;
3321           }
3322       (*mangled) += 2;
3323       break;
3324 
3325     case '0':
3326     default:
3327       success = 0;
3328     }
3329 
3330   if (!success)
3331     return success;
3332 
3333   /* Pick off the names and collect them in the temp buffer in the order
3334      in which they are found, separated by '::'.  */
3335 
3336   while (qualifiers-- > 0)
3337     {
3338       int remember_K = 1;
3339       string_clear (&last_name);
3340 
3341       if (*mangled[0] == '_')
3342           (*mangled)++;
3343 
3344       if (*mangled[0] == 't')
3345           {
3346             /* Here we always append to TEMP since we will want to use
3347                the template name without the template parameters as a
3348                constructor or destructor name.  The appropriate
3349                (parameter-less) value is returned by demangle_template
3350                in LAST_NAME.  We do not remember the template type here,
3351                in order to match the G++ mangling algorithm.  */
3352             success = demangle_template(work, mangled, &temp,
3353                                               &last_name, 1, 0);
3354             if (!success)
3355               break;
3356           }
3357       else if (*mangled[0] == 'K')
3358           {
3359           int idx;
3360           (*mangled)++;
3361           idx = consume_count_with_underscores (mangled);
3362           if (idx == -1 || idx >= work->numk)
3363             success = 0;
3364           else
3365             string_append (&temp, work->ktypevec[idx]);
3366           remember_K = 0;
3367 
3368             if (!success) break;
3369           }
3370       else
3371           {
3372             if (EDG_DEMANGLING)
3373             {
3374                 int namelength;
3375                 /* Now recursively demangle the qualifier
3376                  * This is necessary to deal with templates in
3377                  * mangling styles like EDG */
3378                 namelength = consume_count (mangled);
3379                 if (namelength == -1)
3380                     {
3381                       success = 0;
3382                       break;
3383                     }
3384                 recursively_demangle(work, mangled, &temp, namelength);
3385             }
3386           else
3387             {
3388               string_delete (&last_name);
3389               success = do_type (work, mangled, &last_name);
3390               if (!success)
3391                 break;
3392               string_appends (&temp, &last_name);
3393             }
3394           }
3395 
3396       if (remember_K)
3397           remember_Ktype (work, temp.b, LEN_STRING (&temp));
3398 
3399       if (qualifiers > 0)
3400           string_append (&temp, SCOPE_STRING (work));
3401     }
3402 
3403   remember_Btype (work, temp.b, LEN_STRING (&temp), bindex);
3404 
3405   /* If we are using the result as a function name, we need to append
3406      the appropriate '::' separated constructor or destructor name.
3407      We do this here because this is the most convenient place, where
3408      we already have a pointer to the name and the length of the name.  */
3409 
3410   if (isfuncname)
3411     {
3412       string_append (&temp, SCOPE_STRING (work));
3413       if (work -> destructor & 1)
3414           string_append (&temp, "~");
3415       string_appends (&temp, &last_name);
3416     }
3417 
3418   /* Now either prepend the temp buffer to the result, or append it,
3419      depending upon the state of the append flag.  */
3420 
3421   if (append)
3422     string_appends (result, &temp);
3423   else
3424     {
3425       if (!STRING_EMPTY (result))
3426           string_append (&temp, SCOPE_STRING (work));
3427       string_prepends (result, &temp);
3428     }
3429 
3430   string_delete (&last_name);
3431   string_delete (&temp);
3432   return (success);
3433 }
3434 
3435 /*
3436 
3437 LOCAL FUNCTION
3438 
3439           get_count -- convert an ascii count to integer, consuming tokens
3440 
3441 SYNOPSIS
3442 
3443           static int
3444           get_count (const char **type, int *count)
3445 
3446 DESCRIPTION
3447 
3448           Assume that *type points at a count in a mangled name; set
3449           *count to its value, and set *type to the next character after
3450           the count.  There are some weird rules in effect here.
3451 
3452           If *type does not point at a string of digits, return zero.
3453 
3454           If *type points at a string of digits followed by an
3455           underscore, set *count to their value as an integer, advance
3456           *type to point *after the underscore, and return 1.
3457 
3458           If *type points at a string of digits not followed by an
3459           underscore, consume only the first digit.  Set *count to its
3460           value as an integer, leave *type pointing after that digit,
3461           and return 1.
3462 
3463         The excuse for this odd behavior: in the ARM and HP demangling
3464         styles, a type can be followed by a repeat count of the form
3465         `Nxy', where:
3466 
3467         `x' is a single digit specifying how many additional copies
3468             of the type to append to the argument list, and
3469 
3470         `y' is one or more digits, specifying the zero-based index of
3471             the first repeated argument in the list.  Yes, as you're
3472             unmangling the name you can figure this out yourself, but
3473             it's there anyway.
3474 
3475         So, for example, in `bar__3fooFPiN51', the first argument is a
3476         pointer to an integer (`Pi'), and then the next five arguments
3477         are the same (`N5'), and the first repeat is the function's
3478         second argument (`1').
3479 */
3480 
3481 static int
get_count(const char ** type,int * count)3482 get_count (const char **type, int *count)
3483 {
3484   const char *p;
3485   int n;
3486 
3487   if (!ISDIGIT ((unsigned char)**type))
3488     return (0);
3489   else
3490     {
3491       *count = **type - '0';
3492       (*type)++;
3493       if (ISDIGIT ((unsigned char)**type))
3494           {
3495             p = *type;
3496             n = *count;
3497             do
3498               {
3499                 n *= 10;
3500                 n += *p - '0';
3501                 p++;
3502               }
3503             while (ISDIGIT ((unsigned char)*p));
3504             if (*p == '_')
3505               {
3506                 *type = p + 1;
3507                 *count = n;
3508               }
3509           }
3510     }
3511   return (1);
3512 }
3513 
3514 /* RESULT will be initialised here; it will be freed on failure.  The
3515    value returned is really a type_kind_t.  */
3516 
3517 static int
do_type(struct work_stuff * work,const char ** mangled,string * result)3518 do_type (struct work_stuff *work, const char **mangled, string *result)
3519 {
3520   int n;
3521   int done;
3522   int success;
3523   string decl;
3524   const char *remembered_type;
3525   int type_quals;
3526   type_kind_t tk = tk_none;
3527 
3528   string_init (&decl);
3529   string_init (result);
3530 
3531   done = 0;
3532   success = 1;
3533   while (success && !done)
3534     {
3535       int member;
3536       switch (**mangled)
3537           {
3538 
3539             /* A pointer type */
3540           case 'P':
3541           case 'p':
3542             (*mangled)++;
3543             if (! (work -> options & DMGL_JAVA))
3544               string_prepend (&decl, "*");
3545             if (tk == tk_none)
3546               tk = tk_pointer;
3547             break;
3548 
3549             /* A reference type */
3550           case 'R':
3551             (*mangled)++;
3552             string_prepend (&decl, "&");
3553             if (tk == tk_none)
3554               tk = tk_reference;
3555             break;
3556 
3557             /* An array */
3558           case 'A':
3559             {
3560               ++(*mangled);
3561               if (!STRING_EMPTY (&decl)
3562                     && (decl.b[0] == '*' || decl.b[0] == '&'))
3563                 {
3564                     string_prepend (&decl, "(");
3565                     string_append (&decl, ")");
3566                 }
3567               string_append (&decl, "[");
3568               if (**mangled != '_')
3569                 success = demangle_template_value_parm (work, mangled, &decl,
3570                                                                   tk_integral);
3571               if (**mangled == '_')
3572                 ++(*mangled);
3573               string_append (&decl, "]");
3574               break;
3575             }
3576 
3577           /* A back reference to a previously seen type */
3578           case 'T':
3579             (*mangled)++;
3580             if (!get_count (mangled, &n) || n >= work -> ntypes)
3581               {
3582                 success = 0;
3583               }
3584             else
3585               {
3586                 remembered_type = work -> typevec[n];
3587                 mangled = &remembered_type;
3588               }
3589             break;
3590 
3591             /* A function */
3592           case 'F':
3593             (*mangled)++;
3594               if (!STRING_EMPTY (&decl)
3595                     && (decl.b[0] == '*' || decl.b[0] == '&'))
3596               {
3597                 string_prepend (&decl, "(");
3598                 string_append (&decl, ")");
3599               }
3600             /* After picking off the function args, we expect to either find the
3601                function return type (preceded by an '_') or the end of the
3602                string.  */
3603             if (!demangle_nested_args (work, mangled, &decl)
3604                 || (**mangled != '_' && **mangled != '\0'))
3605               {
3606                 success = 0;
3607                 break;
3608               }
3609             if (success && (**mangled == '_'))
3610               (*mangled)++;
3611             break;
3612 
3613           case 'M':
3614           case 'O':
3615             {
3616               type_quals = TYPE_UNQUALIFIED;
3617 
3618               member = **mangled == 'M';
3619               (*mangled)++;
3620 
3621               string_append (&decl, ")");
3622 
3623               /* We don't need to prepend `::' for a qualified name;
3624                  demangle_qualified will do that for us.  */
3625               if (**mangled != 'Q')
3626                 string_prepend (&decl, SCOPE_STRING (work));
3627 
3628               if (ISDIGIT ((unsigned char)**mangled))
3629                 {
3630                     n = consume_count (mangled);
3631                     if (n == -1
3632                         || (int) strlen (*mangled) < n)
3633                       {
3634                         success = 0;
3635                         break;
3636                       }
3637                     string_prependn (&decl, *mangled, n);
3638                     *mangled += n;
3639                 }
3640               else if (**mangled == 'X' || **mangled == 'Y')
3641                 {
3642                     string temp;
3643                     do_type (work, mangled, &temp);
3644                     string_prepends (&decl, &temp);
3645                     string_delete (&temp);
3646                 }
3647               else if (**mangled == 't')
3648                 {
3649                     string temp;
3650                     string_init (&temp);
3651                     success = demangle_template (work, mangled, &temp,
3652                                                        NULL, 1, 1);
3653                     if (success)
3654                       {
3655                         string_prependn (&decl, temp.b, temp.p - temp.b);
3656                         string_delete (&temp);
3657                       }
3658                     else
3659                       break;
3660                 }
3661               else if (**mangled == 'Q')
3662                 {
3663                     success = demangle_qualified (work, mangled, &decl,
3664                                                         /*isfuncnam=*/0,
3665                                                         /*append=*/0);
3666                     if (!success)
3667                       break;
3668                 }
3669               else
3670                 {
3671                     success = 0;
3672                     break;
3673                 }
3674 
3675               string_prepend (&decl, "(");
3676               if (member)
3677                 {
3678                     switch (**mangled)
3679                       {
3680                       case 'C':
3681                       case 'V':
3682                       case 'u':
3683                         type_quals |= code_for_qualifier (**mangled);
3684                         (*mangled)++;
3685                         break;
3686 
3687                       default:
3688                         break;
3689                       }
3690 
3691                     if (*(*mangled)++ != 'F')
3692                       {
3693                         success = 0;
3694                         break;
3695                       }
3696                 }
3697               if ((member && !demangle_nested_args (work, mangled, &decl))
3698                     || **mangled != '_')
3699                 {
3700                     success = 0;
3701                     break;
3702                 }
3703               (*mangled)++;
3704               if (! PRINT_ANSI_QUALIFIERS)
3705                 {
3706                     break;
3707                 }
3708               if (type_quals != TYPE_UNQUALIFIED)
3709                 {
3710                     APPEND_BLANK (&decl);
3711                     string_append (&decl, qualifier_string (type_quals));
3712                 }
3713               break;
3714             }
3715         case 'G':
3716             (*mangled)++;
3717             break;
3718 
3719           case 'C':
3720           case 'V':
3721           case 'u':
3722             if (PRINT_ANSI_QUALIFIERS)
3723               {
3724                 if (!STRING_EMPTY (&decl))
3725                     string_prepend (&decl, " ");
3726 
3727                 string_prepend (&decl, demangle_qualifier (**mangled));
3728               }
3729             (*mangled)++;
3730             break;
3731             /*
3732               }
3733               */
3734 
3735             /* fall through */
3736           default:
3737             done = 1;
3738             break;
3739           }
3740     }
3741 
3742   if (success) switch (**mangled)
3743     {
3744       /* A qualified name, such as "Outer::Inner".  */
3745     case 'Q':
3746     case 'K':
3747       {
3748         success = demangle_qualified (work, mangled, result, 0, 1);
3749         break;
3750       }
3751 
3752     /* A back reference to a previously seen squangled type */
3753     case 'B':
3754       (*mangled)++;
3755       if (!get_count (mangled, &n) || n >= work -> numb)
3756           success = 0;
3757       else
3758           string_append (result, work->btypevec[n]);
3759       break;
3760 
3761     case 'X':
3762     case 'Y':
3763       /* A template parm.  We substitute the corresponding argument. */
3764       {
3765           int idx;
3766 
3767           (*mangled)++;
3768           idx = consume_count_with_underscores (mangled);
3769 
3770           if (idx == -1
3771               || (work->tmpl_argvec && idx >= work->ntmpl_args)
3772               || consume_count_with_underscores (mangled) == -1)
3773             {
3774               success = 0;
3775               break;
3776             }
3777 
3778           if (work->tmpl_argvec)
3779             string_append (result, work->tmpl_argvec[idx]);
3780           else
3781             string_append_template_idx (result, idx);
3782 
3783           success = 1;
3784       }
3785     break;
3786 
3787     default:
3788       success = demangle_fund_type (work, mangled, result);
3789       if (tk == tk_none)
3790           tk = (type_kind_t) success;
3791       break;
3792     }
3793 
3794   if (success)
3795     {
3796       if (!STRING_EMPTY (&decl))
3797           {
3798             string_append (result, " ");
3799             string_appends (result, &decl);
3800           }
3801     }
3802   else
3803     string_delete (result);
3804   string_delete (&decl);
3805 
3806   if (success)
3807     /* Assume an integral type, if we're not sure.  */
3808     return (int) ((tk == tk_none) ? tk_integral : tk);
3809   else
3810     return 0;
3811 }
3812 
3813 /* Given a pointer to a type string that represents a fundamental type
3814    argument (int, long, unsigned int, etc) in TYPE, a pointer to the
3815    string in which the demangled output is being built in RESULT, and
3816    the WORK structure, decode the types and add them to the result.
3817 
3818    For example:
3819 
3820           "Ci"      =>        "const int"
3821           "Sl"      =>        "signed long"
3822           "CUs"     =>        "const unsigned short"
3823 
3824    The value returned is really a type_kind_t.  */
3825 
3826 static int
demangle_fund_type(struct work_stuff * work,const char ** mangled,string * result)3827 demangle_fund_type (struct work_stuff *work,
3828                     const char **mangled, string *result)
3829 {
3830   int done = 0;
3831   int success = 1;
3832   char buf[INTBUF_SIZE + 5 /* 'int%u_t' */];
3833   unsigned int dec = 0;
3834   type_kind_t tk = tk_integral;
3835 
3836   /* First pick off any type qualifiers.  There can be more than one.  */
3837 
3838   while (!done)
3839     {
3840       switch (**mangled)
3841           {
3842           case 'C':
3843           case 'V':
3844           case 'u':
3845             if (PRINT_ANSI_QUALIFIERS)
3846               {
3847               if (!STRING_EMPTY (result))
3848                 string_prepend (result, " ");
3849                 string_prepend (result, demangle_qualifier (**mangled));
3850               }
3851             (*mangled)++;
3852             break;
3853           case 'U':
3854             (*mangled)++;
3855             APPEND_BLANK (result);
3856             string_append (result, "unsigned");
3857             break;
3858           case 'S': /* signed char only */
3859             (*mangled)++;
3860             APPEND_BLANK (result);
3861             string_append (result, "signed");
3862             break;
3863           case 'J':
3864             (*mangled)++;
3865             APPEND_BLANK (result);
3866             string_append (result, "__complex");
3867             break;
3868           default:
3869             done = 1;
3870             break;
3871           }
3872     }
3873 
3874   /* Now pick off the fundamental type.  There can be only one.  */
3875 
3876   switch (**mangled)
3877     {
3878     case '\0':
3879     case '_':
3880       break;
3881     case 'v':
3882       (*mangled)++;
3883       APPEND_BLANK (result);
3884       string_append (result, "void");
3885       break;
3886     case 'x':
3887       (*mangled)++;
3888       APPEND_BLANK (result);
3889       string_append (result, "long long");
3890       break;
3891     case 'l':
3892       (*mangled)++;
3893       APPEND_BLANK (result);
3894       string_append (result, "long");
3895       break;
3896     case 'i':
3897       (*mangled)++;
3898       APPEND_BLANK (result);
3899       string_append (result, "int");
3900       break;
3901     case 's':
3902       (*mangled)++;
3903       APPEND_BLANK (result);
3904       string_append (result, "short");
3905       break;
3906     case 'b':
3907       (*mangled)++;
3908       APPEND_BLANK (result);
3909       string_append (result, "bool");
3910       tk = tk_bool;
3911       break;
3912     case 'c':
3913       (*mangled)++;
3914       APPEND_BLANK (result);
3915       string_append (result, "char");
3916       tk = tk_char;
3917       break;
3918     case 'w':
3919       (*mangled)++;
3920       APPEND_BLANK (result);
3921       string_append (result, "wchar_t");
3922       tk = tk_char;
3923       break;
3924     case 'r':
3925       (*mangled)++;
3926       APPEND_BLANK (result);
3927       string_append (result, "long double");
3928       tk = tk_real;
3929       break;
3930     case 'd':
3931       (*mangled)++;
3932       APPEND_BLANK (result);
3933       string_append (result, "double");
3934       tk = tk_real;
3935       break;
3936     case 'f':
3937       (*mangled)++;
3938       APPEND_BLANK (result);
3939       string_append (result, "float");
3940       tk = tk_real;
3941       break;
3942     case 'G':
3943       (*mangled)++;
3944       if (!ISDIGIT ((unsigned char)**mangled))
3945           {
3946             success = 0;
3947             break;
3948           }
3949     case 'I':
3950       (*mangled)++;
3951       if (**mangled == '_')
3952           {
3953             int i;
3954             (*mangled)++;
3955             for (i = 0;
3956                  i < (long) sizeof (buf) - 1 && **mangled && **mangled != '_';
3957                  (*mangled)++, i++)
3958               buf[i] = **mangled;
3959             if (**mangled != '_')
3960               {
3961                 success = 0;
3962                 break;
3963               }
3964             buf[i] = '\0';
3965             (*mangled)++;
3966           }
3967       else
3968           {
3969             strncpy (buf, *mangled, 2);
3970             buf[2] = '\0';
3971             *mangled += min (strlen (*mangled), 2);
3972           }
3973       sscanf (buf, "%x", &dec);
3974       sprintf (buf, "int%u_t", dec);
3975       APPEND_BLANK (result);
3976       string_append (result, buf);
3977       break;
3978 
3979       /* fall through */
3980       /* An explicit type, such as "6mytype" or "7integer" */
3981     case '0':
3982     case '1':
3983     case '2':
3984     case '3':
3985     case '4':
3986     case '5':
3987     case '6':
3988     case '7':
3989     case '8':
3990     case '9':
3991       {
3992         int bindex = register_Btype (work);
3993         string btype;
3994         string_init (&btype);
3995         if (demangle_class_name (work, mangled, &btype)) {
3996           remember_Btype (work, btype.b, LEN_STRING (&btype), bindex);
3997           APPEND_BLANK (result);
3998           string_appends (result, &btype);
3999         }
4000         else
4001           success = 0;
4002         string_delete (&btype);
4003         break;
4004       }
4005     case 't':
4006       {
4007         string btype;
4008         string_init (&btype);
4009         success = demangle_template (work, mangled, &btype, 0, 1, 1);
4010         string_appends (result, &btype);
4011         string_delete (&btype);
4012         break;
4013       }
4014     default:
4015       success = 0;
4016       break;
4017     }
4018 
4019   return success ? ((int) tk) : 0;
4020 }
4021 
4022 
4023 /* Handle a template's value parameter for HP aCC (extension from ARM)
4024    **mangled points to 'S' or 'U' */
4025 
4026 static int
do_hpacc_template_const_value(struct work_stuff * work ATTRIBUTE_UNUSED,const char ** mangled,string * result)4027 do_hpacc_template_const_value (struct work_stuff *work ATTRIBUTE_UNUSED,
4028                                const char **mangled, string *result)
4029 {
4030   int unsigned_const;
4031 
4032   if (**mangled != 'U' && **mangled != 'S')
4033     return 0;
4034 
4035   unsigned_const = (**mangled == 'U');
4036 
4037   (*mangled)++;
4038 
4039   switch (**mangled)
4040     {
4041       case 'N':
4042         string_append (result, "-");
4043         /* fall through */
4044       case 'P':
4045         (*mangled)++;
4046         break;
4047       case 'M':
4048         /* special case for -2^31 */
4049         string_append (result, "-2147483648");
4050         (*mangled)++;
4051         return 1;
4052       default:
4053         return 0;
4054     }
4055 
4056   /* We have to be looking at an integer now */
4057   if (!(ISDIGIT ((unsigned char)**mangled)))
4058     return 0;
4059 
4060   /* We only deal with integral values for template
4061      parameters -- so it's OK to look only for digits */
4062   while (ISDIGIT ((unsigned char)**mangled))
4063     {
4064       char_str[0] = **mangled;
4065       string_append (result, char_str);
4066       (*mangled)++;
4067     }
4068 
4069   if (unsigned_const)
4070     string_append (result, "U");
4071 
4072   /* FIXME? Some day we may have 64-bit (or larger :-) ) constants
4073      with L or LL suffixes. pai/1997-09-03 */
4074 
4075   return 1; /* success */
4076 }
4077 
4078 /* Handle a template's literal parameter for HP aCC (extension from ARM)
4079    **mangled is pointing to the 'A' */
4080 
4081 static int
do_hpacc_template_literal(struct work_stuff * work,const char ** mangled,string * result)4082 do_hpacc_template_literal (struct work_stuff *work, const char **mangled,
4083                            string *result)
4084 {
4085   int literal_len = 0;
4086   char * recurse;
4087   char * recurse_dem;
4088 
4089   if (**mangled != 'A')
4090     return 0;
4091 
4092   (*mangled)++;
4093 
4094   literal_len = consume_count (mangled);
4095 
4096   if (literal_len <= 0)
4097     return 0;
4098 
4099   /* Literal parameters are names of arrays, functions, etc.  and the
4100      canonical representation uses the address operator */
4101   string_append (result, "&");
4102 
4103   /* Now recursively demangle the literal name */
4104   recurse = XNEWVEC (char, literal_len + 1);
4105   memcpy (recurse, *mangled, literal_len);
4106   recurse[literal_len] = '\000';
4107 
4108   recurse_dem = cplus_demangle (recurse, work->options);
4109 
4110   if (recurse_dem)
4111     {
4112       string_append (result, recurse_dem);
4113       free (recurse_dem);
4114     }
4115   else
4116     {
4117       string_appendn (result, *mangled, literal_len);
4118     }
4119   (*mangled) += literal_len;
4120   free (recurse);
4121 
4122   return 1;
4123 }
4124 
4125 static int
snarf_numeric_literal(const char ** args,string * arg)4126 snarf_numeric_literal (const char **args, string *arg)
4127 {
4128   if (**args == '-')
4129     {
4130       char_str[0] = '-';
4131       string_append (arg, char_str);
4132       (*args)++;
4133     }
4134   else if (**args == '+')
4135     (*args)++;
4136 
4137   if (!ISDIGIT ((unsigned char)**args))
4138     return 0;
4139 
4140   while (ISDIGIT ((unsigned char)**args))
4141     {
4142       char_str[0] = **args;
4143       string_append (arg, char_str);
4144       (*args)++;
4145     }
4146 
4147   return 1;
4148 }
4149 
4150 /* Demangle the next argument, given by MANGLED into RESULT, which
4151    *should be an uninitialized* string.  It will be initialized here,
4152    and free'd should anything go wrong.  */
4153 
4154 static int
do_arg(struct work_stuff * work,const char ** mangled,string * result)4155 do_arg (struct work_stuff *work, const char **mangled, string *result)
4156 {
4157   /* Remember where we started so that we can record the type, for
4158      non-squangling type remembering.  */
4159   const char *start = *mangled;
4160 
4161   string_init (result);
4162 
4163   if (work->nrepeats > 0)
4164     {
4165       --work->nrepeats;
4166 
4167       if (work->previous_argument == 0)
4168           return 0;
4169 
4170       /* We want to reissue the previous type in this argument list.  */
4171       string_appends (result, work->previous_argument);
4172       return 1;
4173     }
4174 
4175   if (**mangled == 'n')
4176     {
4177       /* A squangling-style repeat.  */
4178       (*mangled)++;
4179       work->nrepeats = consume_count(mangled);
4180 
4181       if (work->nrepeats <= 0)
4182           /* This was not a repeat count after all.  */
4183           return 0;
4184 
4185       if (work->nrepeats > 9)
4186           {
4187             if (**mangled != '_')
4188               /* The repeat count should be followed by an '_' in this
4189                  case.  */
4190               return 0;
4191             else
4192               (*mangled)++;
4193           }
4194 
4195       /* Now, the repeat is all set up.  */
4196       return do_arg (work, mangled, result);
4197     }
4198 
4199   /* Save the result in WORK->previous_argument so that we can find it
4200      if it's repeated.  Note that saving START is not good enough: we
4201      do not want to add additional types to the back-referenceable
4202      type vector when processing a repeated type.  */
4203   if (work->previous_argument)
4204     string_delete (work->previous_argument);
4205   else
4206     work->previous_argument = XNEW (string);
4207 
4208   if (!do_type (work, mangled, work->previous_argument))
4209     return 0;
4210 
4211   string_appends (result, work->previous_argument);
4212 
4213   remember_type (work, start, *mangled - start);
4214   return 1;
4215 }
4216 
4217 static void
remember_type(struct work_stuff * work,const char * start,int len)4218 remember_type (struct work_stuff *work, const char *start, int len)
4219 {
4220   char *tem;
4221 
4222   if (work->forgetting_types)
4223     return;
4224 
4225   if (work -> ntypes >= work -> typevec_size)
4226     {
4227       if (work -> typevec_size == 0)
4228           {
4229             work -> typevec_size = 3;
4230             work -> typevec = XNEWVEC (char *, work->typevec_size);
4231           }
4232       else
4233           {
4234             work -> typevec_size *= 2;
4235             work -> typevec
4236               = XRESIZEVEC (char *, work->typevec, work->typevec_size);
4237           }
4238     }
4239   tem = XNEWVEC (char, len + 1);
4240   memcpy (tem, start, len);
4241   tem[len] = '\0';
4242   work -> typevec[work -> ntypes++] = tem;
4243 }
4244 
4245 
4246 /* Remember a K type class qualifier. */
4247 static void
remember_Ktype(struct work_stuff * work,const char * start,int len)4248 remember_Ktype (struct work_stuff *work, const char *start, int len)
4249 {
4250   char *tem;
4251 
4252   if (work -> numk >= work -> ksize)
4253     {
4254       if (work -> ksize == 0)
4255           {
4256             work -> ksize = 5;
4257             work -> ktypevec = XNEWVEC (char *, work->ksize);
4258           }
4259       else
4260           {
4261             work -> ksize *= 2;
4262             work -> ktypevec
4263               = XRESIZEVEC (char *, work->ktypevec, work->ksize);
4264           }
4265     }
4266   tem = XNEWVEC (char, len + 1);
4267   memcpy (tem, start, len);
4268   tem[len] = '\0';
4269   work -> ktypevec[work -> numk++] = tem;
4270 }
4271 
4272 /* Register a B code, and get an index for it. B codes are registered
4273    as they are seen, rather than as they are completed, so map<temp<char> >
4274    registers map<temp<char> > as B0, and temp<char> as B1 */
4275 
4276 static int
register_Btype(struct work_stuff * work)4277 register_Btype (struct work_stuff *work)
4278 {
4279   int ret;
4280 
4281   if (work -> numb >= work -> bsize)
4282     {
4283       if (work -> bsize == 0)
4284           {
4285             work -> bsize = 5;
4286             work -> btypevec = XNEWVEC (char *, work->bsize);
4287           }
4288       else
4289           {
4290             work -> bsize *= 2;
4291             work -> btypevec
4292               = XRESIZEVEC (char *, work->btypevec, work->bsize);
4293           }
4294     }
4295   ret = work -> numb++;
4296   work -> btypevec[ret] = NULL;
4297   return(ret);
4298 }
4299 
4300 /* Store a value into a previously registered B code type. */
4301 
4302 static void
remember_Btype(struct work_stuff * work,const char * start,int len,int index)4303 remember_Btype (struct work_stuff *work, const char *start,
4304                 int len, int index)
4305 {
4306   char *tem;
4307 
4308   tem = XNEWVEC (char, len + 1);
4309   memcpy (tem, start, len);
4310   tem[len] = '\0';
4311   work -> btypevec[index] = tem;
4312 }
4313 
4314 /* Lose all the info related to B and K type codes. */
4315 static void
forget_B_and_K_types(struct work_stuff * work)4316 forget_B_and_K_types (struct work_stuff *work)
4317 {
4318   int i;
4319 
4320   while (work -> numk > 0)
4321     {
4322       i = --(work -> numk);
4323       if (work -> ktypevec[i] != NULL)
4324           {
4325             free (work -> ktypevec[i]);
4326             work -> ktypevec[i] = NULL;
4327           }
4328     }
4329 
4330   while (work -> numb > 0)
4331     {
4332       i = --(work -> numb);
4333       if (work -> btypevec[i] != NULL)
4334           {
4335             free (work -> btypevec[i]);
4336             work -> btypevec[i] = NULL;
4337           }
4338     }
4339 }
4340 /* Forget the remembered types, but not the type vector itself.  */
4341 
4342 static void
forget_types(struct work_stuff * work)4343 forget_types (struct work_stuff *work)
4344 {
4345   int i;
4346 
4347   while (work -> ntypes > 0)
4348     {
4349       i = --(work -> ntypes);
4350       if (work -> typevec[i] != NULL)
4351           {
4352             free (work -> typevec[i]);
4353             work -> typevec[i] = NULL;
4354           }
4355     }
4356 }
4357 
4358 /* Process the argument list part of the signature, after any class spec
4359    has been consumed, as well as the first 'F' character (if any).  For
4360    example:
4361 
4362    "__als__3fooRT0"           =>        process "RT0"
4363    "complexfunc5__FPFPc_PFl_i"          =>        process "PFPc_PFl_i"
4364 
4365    DECLP must be already initialised, usually non-empty.  It won't be freed
4366    on failure.
4367 
4368    Note that g++ differs significantly from ARM and lucid style mangling
4369    with regards to references to previously seen types.  For example, given
4370    the source fragment:
4371 
4372      class foo {
4373        public:
4374        foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
4375      };
4376 
4377      foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
4378      void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
4379 
4380    g++ produces the names:
4381 
4382      __3fooiRT0iT2iT2
4383      foo__FiR3fooiT1iT1
4384 
4385    while lcc (and presumably other ARM style compilers as well) produces:
4386 
4387      foo__FiR3fooT1T2T1T2
4388      __ct__3fooFiR3fooT1T2T1T2
4389 
4390    Note that g++ bases its type numbers starting at zero and counts all
4391    previously seen types, while lucid/ARM bases its type numbers starting
4392    at one and only considers types after it has seen the 'F' character
4393    indicating the start of the function args.  For lucid/ARM style, we
4394    account for this difference by discarding any previously seen types when
4395    we see the 'F' character, and subtracting one from the type number
4396    reference.
4397 
4398  */
4399 
4400 static int
demangle_args(struct work_stuff * work,const char ** mangled,string * declp)4401 demangle_args (struct work_stuff *work, const char **mangled,
4402                string *declp)
4403 {
4404   string arg;
4405   int need_comma = 0;
4406   int r;
4407   int t;
4408   const char *tem;
4409   char temptype;
4410 
4411   if (PRINT_ARG_TYPES)
4412     {
4413       string_append (declp, "(");
4414       if (**mangled == '\0')
4415           {
4416             string_append (declp, "void");
4417           }
4418     }
4419 
4420   while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e')
4421            || work->nrepeats > 0)
4422     {
4423       if ((**mangled == 'N') || (**mangled == 'T'))
4424           {
4425             temptype = *(*mangled)++;
4426 
4427             if (temptype == 'N')
4428               {
4429                 if (!get_count (mangled, &r))
4430                     {
4431                       return (0);
4432                     }
4433               }
4434             else
4435               {
4436                 r = 1;
4437               }
4438           if ((HP_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) && work -> ntypes >= 10)
4439             {
4440               /* If we have 10 or more types we might have more than a 1 digit
4441                  index so we'll have to consume the whole count here. This
4442                  will lose if the next thing is a type name preceded by a
4443                  count but it's impossible to demangle that case properly
4444                  anyway. Eg if we already have 12 types is T12Pc "(..., type1,
4445                  Pc, ...)"  or "(..., type12, char *, ...)" */
4446               if ((t = consume_count(mangled)) <= 0)
4447                 {
4448                   return (0);
4449                 }
4450             }
4451           else
4452               {
4453                 if (!get_count (mangled, &t))
4454                     {
4455                     return (0);
4456                     }
4457               }
4458             if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
4459               {
4460                 t--;
4461               }
4462             /* Validate the type index.  Protect against illegal indices from
4463                malformed type strings.  */
4464             if ((t < 0) || (t >= work -> ntypes))
4465               {
4466                 return (0);
4467               }
4468             while (work->nrepeats > 0 || --r >= 0)
4469               {
4470                 tem = work -> typevec[t];
4471                 if (need_comma && PRINT_ARG_TYPES)
4472                     {
4473                       string_append (declp, ", ");
4474                     }
4475                 if (!do_arg (work, &tem, &arg))
4476                     {
4477                       return (0);
4478                     }
4479                 if (PRINT_ARG_TYPES)
4480                     {
4481                       string_appends (declp, &arg);
4482                     }
4483                 string_delete (&arg);
4484                 need_comma = 1;
4485               }
4486           }
4487       else
4488           {
4489             if (need_comma && PRINT_ARG_TYPES)
4490               string_append (declp, ", ");
4491             if (!do_arg (work, mangled, &arg))
4492               return (0);
4493             if (PRINT_ARG_TYPES)
4494               string_appends (declp, &arg);
4495             string_delete (&arg);
4496             need_comma = 1;
4497           }
4498     }
4499 
4500   if (**mangled == 'e')
4501     {
4502       (*mangled)++;
4503       if (PRINT_ARG_TYPES)
4504           {
4505             if (need_comma)
4506               {
4507                 string_append (declp, ",");
4508               }
4509             string_append (declp, "...");
4510           }
4511     }
4512 
4513   if (PRINT_ARG_TYPES)
4514     {
4515       string_append (declp, ")");
4516     }
4517   return (1);
4518 }
4519 
4520 /* Like demangle_args, but for demangling the argument lists of function
4521    and method pointers or references, not top-level declarations.  */
4522 
4523 static int
demangle_nested_args(struct work_stuff * work,const char ** mangled,string * declp)4524 demangle_nested_args (struct work_stuff *work, const char **mangled,
4525                       string *declp)
4526 {
4527   string* saved_previous_argument;
4528   int result;
4529   int saved_nrepeats;
4530 
4531   /* The G++ name-mangling algorithm does not remember types on nested
4532      argument lists, unless -fsquangling is used, and in that case the
4533      type vector updated by remember_type is not used.  So, we turn
4534      off remembering of types here.  */
4535   ++work->forgetting_types;
4536 
4537   /* For the repeat codes used with -fsquangling, we must keep track of
4538      the last argument.  */
4539   saved_previous_argument = work->previous_argument;
4540   saved_nrepeats = work->nrepeats;
4541   work->previous_argument = 0;
4542   work->nrepeats = 0;
4543 
4544   /* Actually demangle the arguments.  */
4545   result = demangle_args (work, mangled, declp);
4546 
4547   /* Restore the previous_argument field.  */
4548   if (work->previous_argument)
4549     {
4550       string_delete (work->previous_argument);
4551       free ((char *) work->previous_argument);
4552     }
4553   work->previous_argument = saved_previous_argument;
4554   --work->forgetting_types;
4555   work->nrepeats = saved_nrepeats;
4556 
4557   return result;
4558 }
4559 
4560 /* Returns 1 if a valid function name was found or 0 otherwise.  */
4561 
4562 static int
demangle_function_name(struct work_stuff * work,const char ** mangled,string * declp,const char * scan)4563 demangle_function_name (struct work_stuff *work, const char **mangled,
4564                         string *declp, const char *scan)
4565 {
4566   size_t i;
4567   string type;
4568   const char *tem;
4569 
4570   string_appendn (declp, (*mangled), scan - (*mangled));
4571   string_need (declp, 1);
4572   *(declp -> p) = '\0';
4573 
4574   /* Consume the function name, including the "__" separating the name
4575      from the signature.  We are guaranteed that SCAN points to the
4576      separator.  */
4577 
4578   (*mangled) = scan + 2;
4579   /* We may be looking at an instantiation of a template function:
4580      foo__Xt1t2_Ft3t4, where t1, t2, ... are template arguments and a
4581      following _F marks the start of the function arguments.  Handle
4582      the template arguments first. */
4583 
4584   if (HP_DEMANGLING && (**mangled == 'X'))
4585     {
4586       demangle_arm_hp_template (work, mangled, 0, declp);
4587       /* This leaves MANGLED pointing to the 'F' marking func args */
4588     }
4589 
4590   if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
4591     {
4592 
4593       /* See if we have an ARM style constructor or destructor operator.
4594            If so, then just record it, clear the decl, and return.
4595            We can't build the actual constructor/destructor decl until later,
4596            when we recover the class name from the signature.  */
4597 
4598       if (strcmp (declp -> b, "__ct") == 0)
4599           {
4600             work -> constructor += 1;
4601             string_clear (declp);
4602             return 1;
4603           }
4604       else if (strcmp (declp -> b, "__dt") == 0)
4605           {
4606             work -> destructor += 1;
4607             string_clear (declp);
4608             return 1;
4609           }
4610     }
4611 
4612   if (declp->p - declp->b >= 3
4613       && declp->b[0] == 'o'
4614       && declp->b[1] == 'p'
4615       && strchr (cplus_markers, declp->b[2]) != NULL)
4616     {
4617       /* see if it's an assignment expression */
4618       if (declp->p - declp->b >= 10 /* op$assign_ */
4619             && memcmp (declp->b + 3, "assign_", 7) == 0)
4620           {
4621             for (i = 0; i < ARRAY_SIZE (optable); i++)
4622               {
4623                 int len = declp->p - declp->b - 10;
4624                 if ((int) strlen (optable[i].in) == len
4625                       && memcmp (optable[i].in, declp->b + 10, len) == 0)
4626                     {
4627                       string_clear (declp);
4628                       string_append (declp, "operator");
4629                       string_append (declp, optable[i].out);
4630                       string_append (declp, "=");
4631                       break;
4632                     }
4633               }
4634           }
4635       else
4636           {
4637             for (i = 0; i < ARRAY_SIZE (optable); i++)
4638               {
4639                 int len = declp->p - declp->b - 3;
4640                 if ((int) strlen (optable[i].in) == len
4641                       && memcmp (optable[i].in, declp->b + 3, len) == 0)
4642                     {
4643                       string_clear (declp);
4644                       string_append (declp, "operator");
4645                       string_append (declp, optable[i].out);
4646                       break;
4647                     }
4648               }
4649           }
4650     }
4651   else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
4652              && strchr (cplus_markers, declp->b[4]) != NULL)
4653     {
4654       /* type conversion operator */
4655       tem = declp->b + 5;
4656       if (do_type (work, &tem, &type))
4657           {
4658             string_clear (declp);
4659             string_append (declp, "operator ");
4660             string_appends (declp, &type);
4661             string_delete (&type);
4662           }
4663     }
4664   else if (declp->b[0] == '_' && declp->b[1] == '_'
4665              && declp->b[2] == 'o' && declp->b[3] == 'p')
4666     {
4667       /* ANSI.  */
4668       /* type conversion operator.  */
4669       tem = declp->b + 4;
4670       if (do_type (work, &tem, &type))
4671           {
4672             string_clear (declp);
4673             string_append (declp, "operator ");
4674             string_appends (declp, &type);
4675             string_delete (&type);
4676           }
4677     }
4678   else if (declp->b[0] == '_' && declp->b[1] == '_'
4679              && ISLOWER((unsigned char)declp->b[2])
4680              && ISLOWER((unsigned char)declp->b[3]))
4681     {
4682       if (declp->b[4] == '\0')
4683           {
4684             /* Operator.  */
4685             for (i = 0; i < ARRAY_SIZE (optable); i++)
4686               {
4687                 if (strlen (optable[i].in) == 2
4688                       && memcmp (optable[i].in, declp->b + 2, 2) == 0)
4689                     {
4690                       string_clear (declp);
4691                       string_append (declp, "operator");
4692                       string_append (declp, optable[i].out);
4693                       break;
4694                     }
4695               }
4696           }
4697       else
4698           {
4699             if (declp->b[2] == 'a' && declp->b[5] == '\0')
4700               {
4701                 /* Assignment.  */
4702                 for (i = 0; i < ARRAY_SIZE (optable); i++)
4703                     {
4704                       if (strlen (optable[i].in) == 3
4705                           && memcmp (optable[i].in, declp->b + 2, 3) == 0)
4706                         {
4707                           string_clear (declp);
4708                           string_append (declp, "operator");
4709                           string_append (declp, optable[i].out);
4710                           break;
4711                         }
4712                     }
4713               }
4714           }
4715     }
4716 
4717   /* If a function name was obtained but it's not valid, we were not
4718      successful.  */
4719   if (LEN_STRING (declp) == 1 && declp->b[0] == '.')
4720     return 0;
4721   else
4722     return 1;
4723 }
4724 
4725 /* a mini string-handling package */
4726 
4727 static void
string_need(string * s,int n)4728 string_need (string *s, int n)
4729 {
4730   int tem;
4731 
4732   if (s->b == NULL)
4733     {
4734       if (n < 32)
4735           {
4736             n = 32;
4737           }
4738       s->p = s->b = XNEWVEC (char, n);
4739       s->e = s->b + n;
4740     }
4741   else if (s->e - s->p < n)
4742     {
4743       tem = s->p - s->b;
4744       n += tem;
4745       n *= 2;
4746       s->b = XRESIZEVEC (char, s->b, n);
4747       s->p = s->b + tem;
4748       s->e = s->b + n;
4749     }
4750 }
4751 
4752 static void
string_delete(string * s)4753 string_delete (string *s)
4754 {
4755   if (s->b != NULL)
4756     {
4757       free (s->b);
4758       s->b = s->e = s->p = NULL;
4759     }
4760 }
4761 
4762 static void
string_init(string * s)4763 string_init (string *s)
4764 {
4765   s->b = s->p = s->e = NULL;
4766 }
4767 
4768 static void
string_clear(string * s)4769 string_clear (string *s)
4770 {
4771   s->p = s->b;
4772 }
4773 
4774 #if 0
4775 
4776 static int
4777 string_empty (string *s)
4778 {
4779   return (s->b == s->p);
4780 }
4781 
4782 #endif
4783 
4784 static void
string_append(string * p,const char * s)4785 string_append (string *p, const char *s)
4786 {
4787   int n;
4788   if (s == NULL || *s == '\0')
4789     return;
4790   n = strlen (s);
4791   string_need (p, n);
4792   memcpy (p->p, s, n);
4793   p->p += n;
4794 }
4795 
4796 static void
string_appends(string * p,string * s)4797 string_appends (string *p, string *s)
4798 {
4799   int n;
4800 
4801   if (s->b != s->p)
4802     {
4803       n = s->p - s->b;
4804       string_need (p, n);
4805       memcpy (p->p, s->b, n);
4806       p->p += n;
4807     }
4808 }
4809 
4810 static void
string_appendn(string * p,const char * s,int n)4811 string_appendn (string *p, const char *s, int n)
4812 {
4813   if (n != 0)
4814     {
4815       string_need (p, n);
4816       memcpy (p->p, s, n);
4817       p->p += n;
4818     }
4819 }
4820 
4821 static void
string_prepend(string * p,const char * s)4822 string_prepend (string *p, const char *s)
4823 {
4824   if (s != NULL && *s != '\0')
4825     {
4826       string_prependn (p, s, strlen (s));
4827     }
4828 }
4829 
4830 static void
string_prepends(string * p,string * s)4831 string_prepends (string *p, string *s)
4832 {
4833   if (s->b != s->p)
4834     {
4835       string_prependn (p, s->b, s->p - s->b);
4836     }
4837 }
4838 
4839 static void
string_prependn(string * p,const char * s,int n)4840 string_prependn (string *p, const char *s, int n)
4841 {
4842   char *q;
4843 
4844   if (n != 0)
4845     {
4846       string_need (p, n);
4847       for (q = p->p - 1; q >= p->b; q--)
4848           {
4849             q[n] = q[0];
4850           }
4851       memcpy (p->b, s, n);
4852       p->p += n;
4853     }
4854 }
4855 
4856 static void
string_append_template_idx(string * s,int idx)4857 string_append_template_idx (string *s, int idx)
4858 {
4859   char buf[INTBUF_SIZE + 1 /* 'T' */];
4860   sprintf(buf, "T%d", idx);
4861   string_append (s, buf);
4862 }
4863