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