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